QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2016|回复: 0
打印 上一主题 下一主题

数据结构之数组练习

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-8 09:59 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    数据结构之数组练习7 t, p( D1 g0 D& G$ d- `6 B5 K$ S$ r
    1.leetcode704
    * X  W+ @2 V1 o' a给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。1 G- D5 D3 C  X% i

    1 s! X3 {" ]0 D  g, c题解:升序 数组
    1 P) }$ W2 c' R7 K1 v6 K7 ~* S* a9 `5 T8 T' a
    方法:   二分法8 t! ]7 o$ g; o2 Q1 R

    / E; b" ~9 D$ J1 \! M思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    % h( P* q; p  p( Z, N
    ( L" t0 E4 Z1 s比较nums[mid]和target的值:" `' C1 p0 Z8 b% c1 Z' J* x

    " D  y( x- p5 p$ A- C' p如果nums=target,则下标i即为要寻找的下标;
    6 t; ?1 x- S7 n2 ~2 y' E- w; b4 o8 W9 p- A. r5 {. P# o  r) Z
    如果nums[列]> target,则target 只可能在下标i的左侧;
    9 k* A- M0 r2 Z9 ?
    9 [0 e# h# l1 D* R$ w% R/ w+ o# Zclass Solution {
    5 m8 u2 O) z$ V$ f- Hpublic:
    4 c/ N: S! |3 l7 v3 E: f    int search(vector<int>& nums, int target) {
    4 q. T, [: ?( E/ e* b; h        //区间[left rigth]
    # c( [( P2 ?8 L, ?, {        int left=0;
    / m2 `0 l* `7 U% a9 Q/ N) W        int right=nums.size()-1;
      T7 k( J; `: j8 L        //结束条件 left>rigth6 u. X2 s1 E( W8 k! L* m
            while(left<=right)
    ( h1 ~+ o( u6 z3 v. ]3 y" _+ W        {( Q3 x5 ^' d- ~. ^' q! x7 n- K
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    ' c5 k1 D) |, {            //[middle+1 right]7 D+ {8 g7 k9 }7 h9 `4 H* K
                if(nums[middle]<target)# D; s' e; s* h
                {
    ; l4 u! C% ~9 _2 d+ N: [; ]" r                left=middle+1;
    : k2 |" p6 ]* ^2 x            }7 y4 f& A' J  z7 G( r8 K
                //[left middle-1]: B9 z# r1 \! Y+ r0 y1 b' |& }
                else if(nums[middle]>target)
    % M, H% m! J: r4 A! ^! K( O            {
    * w- M" V9 Y' }  O( o; Q' l6 F                right=middle-1;
    $ r- S; q* S9 _1 M            }( u/ `, H" T% P" P
                else{
    : H8 `- E  F7 v                return middle;# |/ ~% m0 b0 t( \" M! a
                }* A3 A( n- N7 c/ A) h

    9 N; m1 C/ D$ n: }2 o* r6 |        }3 i) }6 W/ \  [& U. y2 t
            return -1;4 a7 m/ [2 ]$ u: [0 a9 F
    ' S* s  Y3 Z9 M5 W+ ^
        }
    6 z# M% P! s; g, Z};
    & o8 J, s9 U" }7 {
    7 l( C9 W# [# E6 E- u  x注意:  l, g% ^3 X$ W' c% M) b
    8 ?2 c7 F# m- Z; t$ s
    (1)设立区间为[left, right],终止条件为left>rigth
    8 O" K8 d0 `8 I8 i' p4 ?$ Q3 o0 P% ~  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    2 b/ M. t# N2 [) g3 L% w2 T0 D  (3)    通过改变区间的左右值;复杂度logn4 K+ f0 _  f: D8 @

    - @1 S6 _( Q1 y2.leetcode 27移除元素+ U- f( }* d$ ]" H) B! K; l
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。1 U* F( R5 ]# r
    6 V$ ~7 b, l" n4 N0 q* d5 b5 u
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。' v3 F$ ]4 [$ b

    ( R" R6 Y  o% d5 |1 z3 W; M元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。/ A& G( h* X; R3 n
    1 x/ x. R5 r3 U
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。, i2 D" u% Z, j+ r8 w
    % t. A+ y8 H5 b
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。  I8 C& t% [1 j& N7 j- [
    8 K+ k6 r2 ^% T+ a, g6 u
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。, v9 J+ Z' t+ w/ t9 Y! H8 q

    . i- k. h- Z, Q' X" ^7 j/ Z9 `: G方法:双指针4 S4 z9 H. B* S1 c( A/ L8 N4 I
    5 V$ V$ t. F$ F' U
    class Solution {: t' s! A9 `* J, Z9 U+ a" L
    public:; b4 @# Y3 |9 v% q+ X
        int removeElement(vector<int>& nums, int val) {
    0 |/ t$ V* H6 T% {/ |           int solwIndex=0;
    + o* l* ]$ N. [: x) t1 k! s           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    & P2 |; D( z" @9 D" i9 A" h           {/ V* E2 A4 T$ g  A9 l
                   if(nums[fastIndex]!=val)4 L; r  i3 h( N
                   {9 ^* ^" ]/ p& e. E+ q0 m- V  }' v
                       nums[solwIndex++]=nums[fastIndex];
    ! G/ N+ ?% B/ w* _# `               }8 g1 U1 U, @( i: |1 |) H; f* U* H
               }, @$ o, l% M  w$ Z. M- A3 @
               return solwIndex;7 c4 n' l0 r# {. Z8 a$ D
        }. h; J, J5 b5 Z4 `: l' v
    };- ^8 V- q" t+ t& K
    solwindex:用来覆盖
    $ E9 B3 F7 P( y7 K& P8 L. @6 h; N5 V. W
    fastindex:来找删除元素++. r& [" N3 C! ?: e) r5 Z
    ; h" N& {+ @% J* d2 O
    3.有序数组的平方; l: s% b1 \8 ^, c# I- n9 E, B
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。* O# ]; }8 G, n* G2 F7 p6 x
    # F. z: X4 `6 O# @4 m; F7 g
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    9 ]5 c2 D8 b" k  ]+ Q* T/ c
    - ~/ o  S5 R! p- r# @+ S那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    ) a4 w8 D  U1 g" Y1 S, N' O1 T& ~0 W, X- U; ~
    此时可以考虑双指针法了,& P( X/ ?/ t! i- [- v6 J
    8 J; u* v8 `4 k& s: h" |
    i指向起始位置(负数),j指向终止位置(正数)。
    & v9 J; P; I7 O; T
    , ?% ?" ~$ h5 j" a定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。% W8 s/ I6 H* B/ L$ T/ O# m
    4 e* ]: m& \1 O4 {! V
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。/ B4 x* |$ C3 O

    $ m' t0 }% f( o- o4 `9 R& g! V4 c如果A * A >= A[j] * A[j] 那么result[k--] = A * A;! P  C0 `9 W' K4 _. h; u
    ; P- I3 X, A$ [) F- X: g' m% {/ Y" F
    class Solution {
    + [$ i* c3 z( J5 E! hpublic:
      g. P: _$ q8 P' h/ L0 F" g) r    vector<int> sortedSquares(vector<int>& A) {
    7 j- ?+ m; W' X        int k=A.size()-1;
    ) G, t6 r0 t" y' J9 f( ?0 Y2 A3 ]        vector<int> result(A.size(),0);. R9 m9 q6 {! y  u# v
            for(int i=0,j=A.size()-1;i<=j;)
    5 C# H7 q/ ^% T( J& ?! D# f        {
    . I- o" o# {+ U: W& u7 u) A' j) D6 L" P            //遍历一遍' {5 X+ z9 p* C7 w- p$ `6 A3 U
                if(A*A<A[j]*A[j])# p. l& U' W; e1 ]& q' p* k
                {
    ! }$ ]. a7 x: s$ t1 G4 M7 p                result[k--]=A[j]*A[j];) ~: g& w! z0 f4 a7 P
                    j--;2 B3 v  Y  X4 L. {1 Q
                }% F( ?2 H; k$ R8 U4 s/ w# i% }- e. c
                else# a8 O. K* y: e  R
                {0 P$ H1 ^) [) E# ~! {- t
                    result[k--]=A*A;# e: g, C9 I" f8 O9 S! Y1 q
                    i++;
    ' M5 ?8 N5 Z) P            }% U. p& k0 c' _9 C3 _
            }; D$ V2 ~' M& ]  u( R
            return result;" ^( f. t" U4 k- P- q
    - c2 M8 U7 x. L
        }( G$ H, [& H+ P! ?0 E9 L
    };
    ) U& y7 `0 o5 W2 W7 a( v0 R. |) ]% h. ~. Z. |' n+ L
    4.长度最小的子数组
    * g. F6 Q& O4 Y" I5 p- A给定一个含有 n 个正整数的数组和一个正整数 target 。5 w" Z* ]: M' {5 X( q  g' ?' ?

    7 H1 ^3 h& Q: E# i& l3 {# Z找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。8 n  m" ~0 R# o% f( |/ V$ g8 O
    7 }9 a" C$ R, U8 k" y& [9 q
    方法:滑动窗口法+ h: T9 O: ]3 v: H  C. D/ Z. M$ G

    , K/ b# V* j% ]4 K  p) @就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。% g! f+ ?1 l/ e) L4 Y7 Q
    / |' S6 W) C" y- O
    三点重要:
    + [0 U% J' L; q
    2 l8 l/ E. t/ o( N窗口内是什么?; @" {6 Z' b% w, j0 b& c
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。0 h7 C3 Q& B3 Z/ r/ G6 i, J$ o
    如何移动窗口的起始位置?3 @0 k+ a0 H; {4 R6 A  x- e
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了6 Q: A' T! l: _0 L5 V8 x
    如何移动窗口的结束位置?
    8 {& ~2 [: \+ R3 f% D窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    " _  v5 y5 S7 x) y5 A' \, y: `. x
    代码如下0 G1 }' }1 e0 q8 x" H9 P

    , H) S) P0 ?9 X3 s, q' Mclass Solution {
    / I3 g* q9 s4 }- x1 p; y3 k; lpublic:6 P6 d- [, y# y$ T
        int minSubArrayLen(int s, vector<int>& nums) {9 P$ O1 {8 m2 J4 j/ L
            int result = INT32_MAX;# _6 m; a4 A6 l9 u5 i; N
            int sum = 0; // 滑动窗口数值之和
    % i. W  z( n6 b- }; H) f6 ]- H        int i = 0; // 滑动窗口起始位置
    $ X# l( V: e' b        int subLength = 0; // 滑动窗口的长度9 T' Z3 X% ]; M% q- L9 e) m# N
            for (int j = 0; j < nums.size(); j++) {& F3 B. Q4 f7 p& Q$ w5 T
                sum += nums[j];- B: c+ |, M) E! _* x7 K3 ^
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件6 J2 _; I( V5 N3 @+ t
                while (sum >= s) {- h* l  p9 m5 i5 t' Q4 _2 I( S
                    subLength = (j - i + 1); // 取子序列的长度4 Q$ C0 @' M6 P
                    result = result < subLength ? result : subLength;//一定会赋值
    " P! M! z4 X5 }  N/ |0 k# d                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)% A' i- [! p, y; [2 d
                }: I2 |) V: Q/ r- P
            }4 ?' `1 |; k  W6 |3 J: w
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    # C0 @) ]1 g# S; J- ^        return result == INT32_MAX ? 0 : result;( x5 k; a; S; ]3 x. j* y: y
        }
    : @) v( X. F; n& G$ I4 w) |};
    : l) B4 [0 t+ ^. M3 W: C9 A3 L2 @0 j0 w8 u
    一旦大于,就减去左区间的值
    ; H5 ^- E8 l& B- k8 @
    ' e. l' P  _  ~' ?8 r  {* P5.最难题螺旋矩阵||) n6 Q+ X4 k3 N' W. t) O4 D
    模拟顺时针画矩阵的过程:
    1 F) [5 N$ Z4 [* e6 k0 M
    7 q4 J, A  w# E; \填充上行从左到右
    / X9 w4 i; e7 L" s, f! \. @9 b填充右列从上到下6 h9 x$ S7 F( z; m
    填充下行从右到左
    ' j) Q# R+ n2 ~6 b填充左列从下到上
    9 ]" |0 `! N' n( S, V( `* j; d& ^由外向内一圈一圈这么画下去。
    4 E) ^' Q( H  S3 k" @" V* n4 Z
    ' n4 W7 @1 y. d( \4 i: q这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。+ y9 t, m$ L* r0 Q) F1 `/ E! Y

    , g9 b* ^/ l* n2 e; k& W6 E
    4 _$ H: N, d. l5 a8 ~
    , X5 z2 u+ q. M& a; n) w: ]9 V! l4 J
    4 |; R1 l* P1 ]8 M$ x9 t
    class Solution {
    & r% {4 I) ^5 A* Ypublic:
      U- I( H4 u% O6 L    vector<vector<int>> generateMatrix(int n) {5 i6 n4 J4 c8 a2 U
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    / j& r0 e( }7 _1 i4 ?/ a! b7 C        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    " K+ p- D) Y8 ~( F1 m, O% J+ d, k        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    1 ~5 }5 b3 ]9 P: T8 \        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    , k( G; z3 f, b9 u. G        int count = 1; // 用来给矩阵中每一个空格赋值7 I, Z) l8 V# T( V& o& n
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    " `  |6 O4 M; C5 l9 n) m$ [( T        int i,j;
    ) G5 q" I7 P" p. Y8 `) t        while (loop --) {
    5 z2 v& t" g# {8 o            i = startx;* ^$ P2 `7 r! k' K  f7 g1 |7 h
                j = starty;/ x- L( d) V+ [, {5 U  r" f

    # X& D) b" n$ n8 i            // 下面开始的四个for就是模拟转了一圈
    8 H" g) j+ C  r# [! Y            // 模拟填充上行从左到右(左闭右开)' o2 ?5 y) t2 [
                for (j = starty; j < n - offset; j++) {
    0 ]% V9 [, [6 J- U0 _3 J$ V                res[startx][j] = count++;
    % E, g! l# d+ {9 q1 R" O" T/ F# W            }
    7 y: U* W1 p7 c* C            // 模拟填充右列从上到下(左闭右开)
    7 w0 K. d( d" y& m            for (i = startx; i < n - offset; i++) {
    9 R2 a) ^1 {4 M. }* B$ f1 [                res[j] = count++;( L7 I+ k7 T, M' J, f7 C' H- v. y" W8 `. c
                }
    5 Q2 @9 Q6 M9 B' r+ j# ^            // 模拟填充下行从右到左(左闭右开)8 k! C) {7 X4 n
                for (; j > starty; j--) {
    4 `7 A( K! L7 F0 x7 P+ T0 e) ~) i                res[j] = count++;
    * F6 l8 r7 \3 Q            }# p, }- N+ y" f2 r% a) V
                // 模拟填充左列从下到上(左闭右开)
    ! M& ?- D. }9 L5 b, o3 I            for (; i > startx; i--) {
    1 U3 S( h% ^  R' P& W8 \9 M0 d3 y                res[j] = count++;% O$ g, ^) S9 Z
                }/ t$ O: I1 p& d' o( Y

    3 K$ _1 ^* R: b6 P* |4 h9 i            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1), L0 B8 F$ g' {9 ]5 u5 V- Q
                startx++;3 m: @$ f+ H$ C( C; `+ P) k
                starty++;  |9 {3 Q) ?, G9 l

    + _* V& \/ }6 m2 M# S            // offset 控制每一圈里每一条边遍历的长度  q. Y; T  \2 H) M7 l0 w) e
                offset += 1;5 j( ^2 ]( v/ m4 ?# \" K5 F8 C  m6 c$ z
            }+ u' n$ {( U7 s4 a3 L/ z& a* E

    8 F2 ]% U# D4 Y! @6 C2 R        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值" n9 V) A( t) f. c3 o6 e, Z" Y! p$ X
            if (n % 2) {
    9 a5 v1 }$ l0 T- t1 m; h            res[mid][mid] = count;
    5 u* |1 r2 Z" }, k        }. k9 Q$ Z: w* P
            return res;% r- @3 F; k3 x: `$ I
        }
    / t8 N2 g0 M* ~2 g! w. X$ l};
    ! N) O1 `7 H4 O. _# C( n! ~- ^' x+ |+ p! g( [8 g; b
    ————————————————1 l5 J7 g/ F! s) S/ a
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    0 L  U: H3 z/ S% _0 ^5 p( P原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    * H1 o# O  Q4 H0 m$ ?, b0 L" h# v% B" }4 }; O

    - C8 U! R( i4 p
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-5-30 17:02 , Processed in 0.312401 second(s), 51 queries .

    回顶部