QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2040|回复: 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
    数据结构之数组练习* @8 X+ a; W  R7 @
    1.leetcode704: v9 i. v9 U& I* M/ P6 b
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    ' }; _. h2 w% l6 h
    ) b3 F) @7 n4 ?9 K题解:升序 数组
    8 S. @3 J6 j, u( Z- A$ C% @3 p; Z& D- a
    方法:   二分法
      J* z5 f" w+ j0 k
    3 S- I' ^% y2 \1 |* ]) x. T" J思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    3 \" o( }( ^. I$ A8 E, X. }) @9 M) k$ S: r5 _9 y5 I
    比较nums[mid]和target的值:! n3 ^( Z8 U& V
    * D9 i9 a8 k) T8 r( s) ^
    如果nums=target,则下标i即为要寻找的下标;2 `* w( _8 T3 F! `- E3 |

    ! F, D6 k& Q  Q如果nums[列]> target,则target 只可能在下标i的左侧;
    6 \7 h+ E% z- ?% X) ?4 `2 L9 X) q5 l6 ]! U  V" T
    class Solution {
    8 y& X1 e  ~) k3 E# dpublic:1 c! `1 }5 S4 U  x$ ~0 S. U
        int search(vector<int>& nums, int target) {$ }  o: F4 ^- X: Q
            //区间[left rigth]
    # G4 M) D& D# J& G        int left=0;
    * G2 F" F! Y4 k. y4 {  P; ?8 x        int right=nums.size()-1;" v4 N( T+ h: W$ {3 _) _7 x, m2 n' h: c
            //结束条件 left>rigth9 ?( N( O. w" Q  A, M
            while(left<=right)
    & \0 s3 N% \0 r7 U1 J$ V. p, X" V        {
    * U7 |- u# R# d! s( X            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    ) h# i- |) `& Q            //[middle+1 right]; Q( @7 z- V2 A5 C
                if(nums[middle]<target)
    - O& m" S1 y- p0 x' j8 c            {
    ( q# V5 o3 Y# b6 m0 |                left=middle+1;
    " N) f* X5 ~( K            }+ ~1 D+ I. n+ W6 R% ]0 M
                //[left middle-1]( Q$ w# p9 ~! A7 C6 a  @, e
                else if(nums[middle]>target)' O7 w0 `9 p9 U) U' O; g0 E/ r
                {. h: I# o( k* i+ N
                    right=middle-1;/ G$ t" B9 ?, t# H0 e* J6 S' k+ Y
                }& t% |4 @+ K) [. m' O" p
                else{
    , P) K. Z( a5 `; L0 |+ x                return middle;
    * k6 w, `& F- F$ A( i7 h            }- ~8 q4 a2 s. @) V/ s
    / n8 v% \9 F7 \4 B1 a! C. m
            }
    ( ^5 u' @) F, R" w        return -1;
    $ }0 {4 V% y- G8 j" j( F: n5 k+ C# O" U/ D3 V# R9 {' v
        }
    8 R* T8 x1 R# {2 l% M- p! [' y5 j};( W0 W5 s) V4 [2 A  U/ S
    : N' W8 c, q) F. @
    注意:8 }! b: R" h! q, q) n& \

    / T+ C, U# Z4 C7 y9 A  v(1)设立区间为[left, right],终止条件为left>rigth( Q5 \- q' Z+ a( t
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    " |7 e3 [7 k) u- @  (3)    通过改变区间的左右值;复杂度logn
    ; q" m! o: V: {& N4 h, i. ^$ x6 K7 ]+ e9 d% j6 c
    2.leetcode 27移除元素7 i# ^! p3 X! H& g# o
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。+ J" k' _5 A9 W, G) v" u$ ~, L

    % M" f" d& ]2 W8 ~) [5 V# d不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。6 w  W  ~& O' V, v5 R/ f* u' P- F/ X

    + W5 l2 {2 ^: J  \* I- P元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    $ P- T4 ^) k1 A+ I; j7 K# d3 [3 i: ~) |. t1 Q
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    : [; L3 Z* j, l0 {2 j8 \+ J, V- g# P3 t* n; t- |, g, K
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    2 X" `% ^3 V% a6 w! B, ?8 Y+ `- G# X8 T
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。: k' b# Z# L; ^2 ?) x1 Q! B
    # Y+ W; e* v& m* w& A- P
    方法:双指针
    6 d5 S$ R7 X7 b+ `: o9 L! C
    % B+ m, T- X  g# A* B  |class Solution {
    4 H; i' |) q, ppublic:
    ' i# Y. k5 s0 j0 z4 ]    int removeElement(vector<int>& nums, int val) {
    # u0 {$ p; j9 D  h$ H$ I/ `* M7 g           int solwIndex=0;  i$ u1 C/ `- k! T+ B5 Z- E. r. E& {
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)4 |3 e5 V/ @+ h# m6 I1 I) C7 I0 O- W
               {
    0 E: ]1 I4 m$ N/ u9 \* `- Y/ H" |               if(nums[fastIndex]!=val)
    & w' o% A& |" l) V$ t& k% j               {
    : T- I/ R- n% j                   nums[solwIndex++]=nums[fastIndex];
    3 ^0 y$ Z8 j7 D5 a6 r; a               }& N$ z2 Z* \& |- M0 G" s
               }1 c  N2 k. w. I, g- B; H: D
               return solwIndex;
    1 n3 `: l% m6 F! V" z$ e    }+ ~( j$ F4 D: {" B; n
    };
    ( o! T6 h6 v, l# Y  X2 ?7 Bsolwindex:用来覆盖
    * |, E, j; z- s# f! c1 k( o/ h6 o
    fastindex:来找删除元素++  R% [  y5 f/ C3 Z

    , R' l) R* P4 x: C3.有序数组的平方
    6 a  f) f+ O" J; \给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。0 w8 F0 a( S( l3 }7 f
    ! |' A0 y1 w5 C  M6 y- U
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    # _3 D( Q; J, a/ H  y* d& e1 p$ S3 H1 W; [
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。6 X  Q# _0 W3 m( j6 ^5 |% l
    6 `$ v8 h- b- P: ^: _
    此时可以考虑双指针法了," ^0 B: I( G$ P- q" r1 B

    8 s; g+ d* t& o) j. I) vi指向起始位置(负数),j指向终止位置(正数)。
    6 B3 F3 t7 X5 d( L
    $ i/ W" C* p* ?  c3 P  X% n3 j8 _- s定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。9 ?& ~6 s+ Q3 o8 d" I

    ; j3 F, d" N- k如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ! ^( c: {3 P9 d0 L/ |8 l/ _+ g# Q
    & \; A& q6 D! i! c如果A * A >= A[j] * A[j] 那么result[k--] = A * A;1 K: B0 H9 p; O) d+ _

    . O0 y: |. n* U% t5 l3 {8 r( X  hclass Solution {8 I, f( q8 j9 U5 F  n$ P
    public:
    & a& K$ F, `# b$ a$ }: p) Z    vector<int> sortedSquares(vector<int>& A) {8 l; o9 I4 _6 p( o
            int k=A.size()-1;; z% J+ ~! M+ {, G6 i5 q
            vector<int> result(A.size(),0);( A' X, j) s/ H  B1 R
            for(int i=0,j=A.size()-1;i<=j;)
    - w+ a) ]- r, j& {: W        {
    + ?  l' g/ E! n) v* i' b            //遍历一遍3 R% K0 r% I  S! L- h
                if(A*A<A[j]*A[j])9 Q/ f& I. n: w& l$ m
                {
    ' s, I: X- z$ |4 K! V# m: Z4 H7 G                result[k--]=A[j]*A[j];
    0 s9 i# _- W; i                j--;4 ?" P) H/ V# L: a9 r8 Y9 a$ @
                }
    : J5 e( Q% y. Q) }. s8 r" ^6 H            else
      ~1 V+ O5 k( S" R8 n- |( r6 P  x' l            {
    3 h, E6 W1 Q6 r# N+ ~* L                result[k--]=A*A;! j# p- v" D6 P  k3 E
                    i++;( f, P7 H; m6 K% u- b! p  U
                }  P2 u- C: P8 I1 Y9 n
            }& \' J. s2 I7 W, J8 L0 C& p
            return result;
    9 u: b% O! {+ e+ \
    1 w8 N$ @* |5 [, A5 Z6 x. F    }' E, s7 H1 y3 U) |6 C
    };
    7 _( M& V1 g9 ^2 I- v$ C$ K$ {+ s( j, ~/ g& k
    4.长度最小的子数组
    " l' m: c0 q# p# o2 W给定一个含有 n 个正整数的数组和一个正整数 target 。5 H0 H) l8 T5 }$ ?# z' T
    . j3 v+ h7 I9 I9 N, _, X
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    # I7 y( p: M' O1 p' t
    0 U8 ^4 h8 O  {方法:滑动窗口法6 A7 j7 g3 S2 O! D

    5 J( A4 ^  c* x+ C& m* m就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。  E0 X. o& r# X6 a3 h8 I

    5 E9 |: y! C6 ?# a三点重要:
    6 Y3 ~  x  [5 i8 C4 K: X7 v6 F+ Y! m' Z: U5 d0 T3 U
    窗口内是什么?& m  k$ w( \' _( `9 |" l
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。& G% M9 }& s0 o& b
    如何移动窗口的起始位置?9 N4 h( F" t: \1 d& W$ h5 b4 O
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了2 [( e) K% E! Y' C" D
    如何移动窗口的结束位置?
    , d* W8 j% ?& a! U窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    9 R5 i' [, J" W* C+ g& a7 M% r% Y. p+ b# Y
    代码如下) Z( e+ r6 @/ P- \( b: V
    ) D  Y% y! Z. R. |( X( G8 Z
    class Solution {- _, v% N! H5 i; D! \7 h* ]
    public:
    * A, V$ S/ [& }# q/ W3 c6 l    int minSubArrayLen(int s, vector<int>& nums) {
    ( q8 Q6 q" ]" p$ D/ J4 r        int result = INT32_MAX;
    7 u& G& n' H9 l: C. R        int sum = 0; // 滑动窗口数值之和) C- ~1 d* h+ V% r8 y2 f- G
            int i = 0; // 滑动窗口起始位置* f* r* ^& W5 ]6 j; ^& H/ e) }
            int subLength = 0; // 滑动窗口的长度$ r" u+ y1 k2 x3 q( y+ J
            for (int j = 0; j < nums.size(); j++) {# w, V4 c2 D- O6 [; \* _
                sum += nums[j];# O7 f0 D$ g0 A6 W8 V
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件) S3 c5 [3 h; D0 w- ?
                while (sum >= s) {
    * Q; O  k3 t' l3 u                subLength = (j - i + 1); // 取子序列的长度) L6 u# ~) r% Q3 h: j
                    result = result < subLength ? result : subLength;//一定会赋值8 m9 w) |$ @* H) t5 t2 y! A- B+ c
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)& z  }. W4 ^4 M; m; D0 d! g$ Y
                }
    6 G! Z0 F$ G, L" p        }9 ^0 l' s  {% ^" t
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    1 N" {" J3 ^. z6 x" G        return result == INT32_MAX ? 0 : result;7 D1 A; a/ o9 ^$ S' l
        }
    / p, q5 m" T! O' `};# I" k( W! B* N
    , c" u2 @* j4 W5 Q* ^
    一旦大于,就减去左区间的值; o4 \+ M5 a+ j5 U& [/ Q- [3 A$ h

    8 r) p- [2 z# J  ?& j# c) Q! O) J5.最难题螺旋矩阵||3 W1 X2 B! p% V/ F! N; g
    模拟顺时针画矩阵的过程:
    7 }, f8 M& k; k4 c% `% {7 a9 \
    0 A6 b( y& H2 _6 `% k$ ^7 \填充上行从左到右
    ' N( z4 F/ q0 I) c填充右列从上到下( p3 W( z/ \. E) I
    填充下行从右到左' ?  z; g7 f; a& O# U2 W
    填充左列从下到上
    ' O, a% _5 Y- K2 G由外向内一圈一圈这么画下去。  q; p+ b/ T' G6 l5 o9 N

    + b5 U5 Z: y6 b3 e这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    : A1 B% V- t: n/ o' W
    0 `$ h% u% \7 y) D/ n9 g0 {* v0 k8 f0 {' D
    * u+ S+ ]) u/ u
    : c1 d. q( E$ M2 s; J1 a

    " }; l1 M  u% D" J1 b1 Eclass Solution {
    $ a' B  E) x8 G  Q" x8 T0 tpublic:
    , c! y, v4 ~, y3 l9 p    vector<vector<int>> generateMatrix(int n) {
    3 V2 Y; w+ ^, Z! Z. \0 t4 f- j        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组0 k: |) }) L- h9 K+ X" G
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置' r  ?4 @( o' w
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    2 I/ C# D# x: i3 q  J. e        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    0 Z2 a& a- E9 D# p' P% l. e        int count = 1; // 用来给矩阵中每一个空格赋值
    2 W& ~" t' y( |) Z5 ^        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位! ^8 \0 W$ [* Q7 K: [. ?
            int i,j;
    - e& o4 R* g1 L0 d# U        while (loop --) {
    7 [+ C+ S! J( l2 [* D4 Z            i = startx;" Z5 g; t8 K4 `& d/ q: o6 I
                j = starty;
    ! g$ [3 d9 ~+ z1 m5 \% Q& ^, Y/ U% ^, Y+ s3 X4 |  ]% e
                // 下面开始的四个for就是模拟转了一圈0 p) D8 P: u2 V
                // 模拟填充上行从左到右(左闭右开)
    " L" j+ O& u- u5 O  b7 u( d# ]            for (j = starty; j < n - offset; j++) {* m) ^  r6 q+ t1 l: |- c5 k
                    res[startx][j] = count++;
    ' B; T3 x0 o0 ^, y            }1 S5 {+ }: R8 k) r
                // 模拟填充右列从上到下(左闭右开)  i. b- N8 m1 `
                for (i = startx; i < n - offset; i++) {
    2 w8 J" K4 B7 Z3 C% W6 e+ D$ w1 F                res[j] = count++;5 y8 ~- e) u6 L
                }
    3 R& _+ V) ^, G! D+ r; g5 r$ t( ^            // 模拟填充下行从右到左(左闭右开)
    : P7 a$ a* x- I+ h            for (; j > starty; j--) {
    8 s2 V3 O9 ?3 R. j% B' N! b. q                res[j] = count++;
    ( [$ A8 F; a' |; h0 ?            }) ~, V# r0 d0 Z( Q
                // 模拟填充左列从下到上(左闭右开)
    # n/ `! g2 `8 [) y2 u$ N            for (; i > startx; i--) {
    $ J' C0 P% v+ E7 k7 B                res[j] = count++;( W5 X& T9 A' G- j* W  c$ _* L4 k( k
                }' }! Y  _: o+ r( r
    2 g1 j8 S2 m( _# f3 O
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1), |6 P% e$ r& V6 f3 e
                startx++;
    : @7 H) b8 l1 n% ^$ Q6 y( u            starty++;
    9 a4 s# H0 ^; \; X- s$ s2 R8 p7 j  O
                // offset 控制每一圈里每一条边遍历的长度- b$ U4 D( K& Y9 g; v  L
                offset += 1;
    8 J/ L1 N, {$ Y( [- j; U        }
    + `# @& x) R" s
    ( u0 a( Z  x" N) r        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    ; O& G0 l5 {2 w) U7 Y7 s        if (n % 2) {
    4 k/ R3 G7 y6 V7 |            res[mid][mid] = count;3 x& P) W9 N2 |9 k, b( j, ]8 \0 {( i. I
            }( m) V& X. H8 J: C5 k& w
            return res;
    # e* S* l& v. Z  M: H    }
    - ]6 m* n& }1 ?% K! T2 y3 K};" i0 g2 k- S4 i& q2 e* |8 _

    ' F+ @# Z$ U+ n3 R- _9 F" r' A/ h————————————————$ t* V9 m! z$ q7 D: \# _
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。  P! a% Z, u' i! T
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039) G8 }6 v7 }7 g$ ?) Z9 G
    : Y7 f; B/ j9 G5 j

    / R) x! ?9 t% p) w2 @9 B
    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-7-30 06:18 , Processed in 0.451047 second(s), 50 queries .

    回顶部