QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1988|回复: 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
    数据结构之数组练习
    - a+ `. Q% ^- ^2 F6 }1.leetcode704
      ?6 }4 @% f8 {" b0 u给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    8 r5 w3 H/ k; s, G: G& q! l
    6 w) G5 z: s) J" A( _1 V题解:升序 数组1 G) K6 m- v9 Z) q8 l

    $ R2 }0 U  r0 k. R! H: L5 F方法:   二分法3 y  l8 T2 e2 c; Y1 a
    1 B- s4 [' Q" j- Q( Q7 B3 g% Z8 J
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)3 a3 Z$ A4 W4 {) y" i: @& n
    / e; Q& V( ?. C+ O) R" u
    比较nums[mid]和target的值:
    ! [3 d: m0 r# V0 A& Q4 l5 F
    " i6 v- l/ ~& |% |* I0 T& A! C0 `如果nums=target,则下标i即为要寻找的下标;* }& i% S9 I- H2 D+ l+ Z
    1 n" B% H& U# w  d
    如果nums[列]> target,则target 只可能在下标i的左侧;
    2 |* B) h* G& z: d
    8 j' @9 h+ R+ L! g8 [9 z; T7 gclass Solution {
    7 B/ {- B6 Q& e" E7 npublic:; I8 V" M6 v* G
        int search(vector<int>& nums, int target) {5 P0 Y9 r" W) W4 F' V7 L
            //区间[left rigth]
    + H2 Z$ }1 M0 f4 ^        int left=0;( h7 F1 m; T6 v% j
            int right=nums.size()-1;$ N) _& z9 F, O* h1 ]
            //结束条件 left>rigth7 d; a% a" j5 s3 A- e
            while(left<=right)) Q; x* q2 E7 m' l; l" {4 r- E
            {( H0 r' Y5 B) e# Q) ^) u- @; b
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]9 e. `' p* t) L; E0 z0 g, B! W0 T
                //[middle+1 right]
    ! P# L4 v/ w( Z6 E) b. Z1 ?$ D            if(nums[middle]<target)
    9 X" V2 y- ~, ^* u2 e            {
    7 U" E  e! w+ U3 U! S% w' _4 C                left=middle+1;
    ; u' @' `( n* L: o/ N4 R/ z            }6 w$ C- P! @. }, B+ ^1 B
                //[left middle-1]5 O. r" J; ~( O9 h) S" ]
                else if(nums[middle]>target)
    # f5 t& f: d& i$ \5 T            {
    3 q6 F( Z0 f* W# ?: m/ M0 t- I5 k) C                right=middle-1;
    - a2 c# F- f. t            }/ x, o3 R% S5 G% H
                else{9 ^4 H" q, T8 O* c- D% \4 M
                    return middle;
    , f+ X; F0 Y6 D) C+ |            }
    8 y4 M) G2 }1 }8 x+ T; z2 I4 V5 Y7 H0 K0 V2 r5 D  u
            }  w. f8 |! N) {$ s: D" [8 `0 V2 t
            return -1;
    / `' F, ^: S0 t2 r
    " W6 _0 `, ]  J2 w( h2 t  `% ^9 p    }
    9 O6 V  V$ n' x- I* w; @, k( _};
    $ c! s$ Q) ^) e4 o6 m' t( r+ ?
    6 j5 `$ R" Z) @$ K" q8 O4 Q3 u注意:- z2 J# Q/ ?1 z( E8 F) h

    6 ^+ @1 p( _' |! ?(1)设立区间为[left, right],终止条件为left>rigth
    ' z' K5 |; S( }5 z/ z0 T$ D0 W  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    ) M, E  f) z3 P8 \8 x  (3)    通过改变区间的左右值;复杂度logn
    , [& j7 ~! j* Y4 A3 h7 E0 g( Q! L* [$ [- r4 G  B
    2.leetcode 27移除元素+ c. W- K8 R  }' ]
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。9 f8 ?- @4 }; c4 E( z5 u/ R4 y. P
    8 ]7 h& K$ o4 v: {% i# B% U! @; r
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    " j$ H& f! l. d( R+ g$ Q4 Y9 G! k8 S1 l. M
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
      U. v$ c8 |% v; V$ A! n! _
    + B- G  f/ C( I1 h' n% P示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。; g* ^, }8 [- G0 {; j

    ) z+ n7 P0 B1 o$ ]示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    . y/ W) Z  C- i; w& v% D0 v* `/ g, j. i% h
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。; V8 b6 X+ v3 z; b
    ! ^8 r; ?4 A) i  C4 m* c# X
    方法:双指针
    7 b0 @3 c- V( O, T% k5 q! }( \) Y
    1 T" E4 d* g3 n5 r) x6 [class Solution {0 Z# e3 D9 c: W7 o: \( ~
    public:1 e5 v2 s; R0 _% l  r
        int removeElement(vector<int>& nums, int val) {
    5 v  c% O2 b4 e' N           int solwIndex=0;
    ' a/ X% h  z4 T& i  b           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    ( Z; l8 J! t8 I$ h6 n2 r7 \/ ^           {: V* `9 D+ n4 [- Z% }; u8 x
                   if(nums[fastIndex]!=val)! S- F- x, S  J  L: n- t& j
                   {- L; m( B  H( o1 E5 E
                       nums[solwIndex++]=nums[fastIndex];
    / a0 F4 T9 Y; I' V) p/ G               }3 _* @6 G6 Y  e1 f% u- |; Z0 Z7 S9 E
               }5 d, c# `/ n$ [! P4 |
               return solwIndex;' h/ v9 R7 f  X7 y
        }
      e4 V" @8 y& I9 }& v};7 z9 Y9 r% f5 V1 j$ @
    solwindex:用来覆盖
    - t! M7 |5 d$ b3 W
    ' ~& g) z/ f/ B4 q. S- Y1 `* @8 ?# bfastindex:来找删除元素++
    0 |6 X' v0 H, g" s
    . z( ~  L8 K/ [% f6 b: s3.有序数组的平方
    * l! p# t% R% W' L* i8 b( h# @给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。2 o. G/ G3 P4 Q: ]6 i
    $ x5 h6 ^" H% O# r* q
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。# r/ T  |! B% t1 K! W( J

    6 U" E8 I6 \$ J( |. O- l3 w那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。. v9 ^+ o" B5 `' D- d

    ( ]& a0 u/ j8 ^4 \" s7 {0 y+ z6 F此时可以考虑双指针法了,
    ; b0 `! w: U' D2 q- e$ r9 U9 G. P5 a! K/ F9 e$ P) p- d
    i指向起始位置(负数),j指向终止位置(正数)。4 q: z) Y' r, K4 K/ o

    + }: v3 u. S3 l定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    0 M' j; O3 ], D. y& }& ?. ?8 W3 @9 G& x+ D7 L" K
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    & v, Y+ I" ~( c4 V  h2 U; K1 d8 X4 w% y( X4 A2 G7 r7 S
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;7 v' t- H. r9 E# I% c
    5 V  R% i- t3 \' l5 C, \
    class Solution {
    6 F- f  i# {" d, dpublic:9 \' A: L9 T" a: v( h
        vector<int> sortedSquares(vector<int>& A) {
    # V) Y% P9 c1 N  z' ]% Q) Z4 t        int k=A.size()-1;
      \; [4 s) {, Q( N* ^! Z        vector<int> result(A.size(),0);
    $ M" N# |7 O: I# z4 X8 a: C        for(int i=0,j=A.size()-1;i<=j;)2 H3 G; J) |% G( C/ j" M& X2 M# J
            {$ G, ]2 }! \5 O# H
                //遍历一遍& \6 E8 @  I, b
                if(A*A<A[j]*A[j])
    * d, [2 H9 V  X3 I2 r7 Y            {8 ~$ g' t6 Q/ }2 |, {
                    result[k--]=A[j]*A[j];% y: j) @" k8 J
                    j--;
    % t! i4 z+ J+ A( F% W* i* p! C! ~            }. i% U5 \1 O0 e6 Y
                else" A3 b6 A( O) @+ ~" c
                {' a. D# }: ^. d4 o  S; x
                    result[k--]=A*A;/ a. c4 O) j' e6 Q7 |0 |
                    i++;) n/ y5 P! `3 W
                }
    , h+ r0 ?3 n- q9 k+ Q        }' t- n# c, b! m& h
            return result;
    1 o# }7 J/ c" @7 k+ x3 @
    - y' h" U+ @) l( M1 J    }, o: W6 P; l# l8 F) x/ R) A- y* ]
    };- ^6 ~3 Q; k0 j2 a! m# h& B& u4 P

    ; i: _  f1 Z0 z! H) s$ v+ v' ?1 @0 h4.长度最小的子数组
    9 V( j4 O2 |7 e$ k% f# l! ~1 E4 J给定一个含有 n 个正整数的数组和一个正整数 target 。
    1 a) ~3 Z& W8 P' ^8 J& U! k/ r* u$ V- D1 h# ^" k
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    7 l- k  R: N, x- i0 I
    ( {- F$ j2 }% m$ K0 M4 a$ J方法:滑动窗口法4 a( W8 Y' P: t2 e% c* Z

    8 F- o- }9 f! D. r3 i, k& x1 a+ X就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。1 w- g/ R& b  S/ k" ]
    0 j8 v! W- k8 _' @3 D% {' p; W
    三点重要:
    # i+ o7 L+ m& L( u* g. o3 E9 y6 q! |" m/ t7 V2 a8 p" [% I
    窗口内是什么?
    , h) N& l$ \% {2 ]. _0 O! @窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    # ~; N- j, n# C. k! \9 J如何移动窗口的起始位置?8 ~+ C9 k2 r1 f3 c0 g: _/ O
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    + y" |# A0 Y/ m* H, l# v如何移动窗口的结束位置?7 p4 Y; }" S5 O* Q: {1 t! k/ Q, [5 h
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。3 o, b( a+ z+ C4 D; I
    & l* j: s) b; b  [5 s# ~, k
    代码如下
      g6 V( C7 x3 T# ^: Q+ _0 q/ u
    " b; w% S4 \% i0 S) T2 L' Wclass Solution {
    ' n' Y7 g, \/ `0 Y6 J0 Tpublic:
    ' |2 p" ^) I$ Q( M; N1 \    int minSubArrayLen(int s, vector<int>& nums) {9 i" |* k# `6 O& u8 ?
            int result = INT32_MAX;
    ) C1 c( p9 b, k        int sum = 0; // 滑动窗口数值之和
    ) {. y7 H7 M' g: I        int i = 0; // 滑动窗口起始位置
    # [) k( e* O0 c( K( t, e        int subLength = 0; // 滑动窗口的长度
    ) u8 j! {, @% G& Q; i        for (int j = 0; j < nums.size(); j++) {
    1 B# j% `' a3 N3 D            sum += nums[j];
    * J+ j5 j. f6 f3 f2 R7 R' {! o; d            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    4 Y; r. F" f+ y! K) ^- O/ o# n            while (sum >= s) {4 T. k, D& h  D% {
                    subLength = (j - i + 1); // 取子序列的长度
    . @( i% w2 o0 B& Y2 c                result = result < subLength ? result : subLength;//一定会赋值. D3 `: m) O8 R) ?5 ?$ C4 b1 _  ^
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    ' o! n4 I: Y8 s! o  n, K            }$ U! J: f% Y! G) w
            }5 E) {4 T% }- d. w2 _% J! Y
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    , }9 \1 T/ y. m' a! [& A        return result == INT32_MAX ? 0 : result;
    & p  X* G- k- a% A0 q: O) _9 s    }
    + O8 F0 ~! t6 X};
    4 {2 m  \5 ~+ _. \. a/ d8 a* c, O& L6 @. b! L- ^* L
    一旦大于,就减去左区间的值& i1 x9 j+ x' F/ [% s& p

    5 M  N, R  B+ j4 d/ n) ]" T4 f5.最难题螺旋矩阵||
    - Z' _: V3 J3 V2 R7 ^& z% H' @模拟顺时针画矩阵的过程:
    2 Z  ~% x' {" D$ a- x" B# J; u0 R; Y% b) e# U
    填充上行从左到右
    - R) W9 L/ G& @8 V# i1 k6 r8 T- U填充右列从上到下
    4 R% T( s& o3 G6 m4 L填充下行从右到左
    3 W8 i( A  a+ N  ?. F* v! {填充左列从下到上
    3 s0 Q5 S1 e2 ~8 @由外向内一圈一圈这么画下去。1 x% z/ x- B! r6 F% ^- o+ d" i
    ( D. G) Q' C2 u! p
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    + I$ @/ q; C* D1 L* x9 q1 M% S5 K3 Z1 S; P; }- I) Q' x
    0 z; m: ~% b8 t2 h5 q/ j

    : q5 z, y! Q+ o8 p8 n/ a8 [" u6 b; V
    : l8 ?( L: v( s6 }6 x. R4 u
    class Solution {
    + ~  A/ h3 @, c& U9 tpublic:
    ) i+ f; R& G1 |  Z1 M! K9 S4 o    vector<vector<int>> generateMatrix(int n) {
    2 e7 l. ], b8 T& j3 u. o  n2 C        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组0 S$ t( b! {2 V% T
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置" y& M' ^+ n, C' h+ b7 B/ ?+ T: v
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    ( x* }7 p+ E4 `9 q, b3 a; G6 m        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    5 T2 [$ y" a1 I7 r3 k0 E        int count = 1; // 用来给矩阵中每一个空格赋值
      S+ [2 X5 s: m        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    2 _* z6 L& g  v" W        int i,j;
    7 E: I+ U( I& _1 e. A8 k        while (loop --) {+ ?- `; S; z  o
                i = startx;7 I% ]- j- N( f9 n4 p9 E
                j = starty;
    + \1 P# U. W5 u6 Q9 O5 f0 J$ ^; ^' H4 [7 @
                // 下面开始的四个for就是模拟转了一圈' e0 E0 q/ m# a: l( a
                // 模拟填充上行从左到右(左闭右开)
    3 H- o2 m3 F" w, K6 |. i            for (j = starty; j < n - offset; j++) {
    , l1 d) Q: T$ R2 l0 U0 g1 [: w& b                res[startx][j] = count++;( R5 u* O: A  }+ j# P" ~7 d( D
                }" ]( o& z, H) M( J9 [
                // 模拟填充右列从上到下(左闭右开)% W/ I" [) D0 |3 e2 d4 |
                for (i = startx; i < n - offset; i++) {
      x# Z$ X3 b# z+ q" A7 I# v                res[j] = count++;
    $ `" f" x; @6 S6 B: r( l            }
    5 K- `( {/ v+ D8 x: s# N            // 模拟填充下行从右到左(左闭右开)
    ; y" ^8 p" B9 Y% i1 C            for (; j > starty; j--) {  Z3 O: S+ o. }) R3 _
                    res[j] = count++;( y8 S) M4 i1 r% B2 e
                }
    9 n2 X+ k1 H3 Z% \/ a5 C  d" p+ u3 c            // 模拟填充左列从下到上(左闭右开)# d; b2 \  Z3 Z! A# X
                for (; i > startx; i--) {
    " _; ]# U+ L; L$ ]# ^; _2 j  e3 H                res[j] = count++;8 X0 }; c7 B' {3 w7 J
                }, s! `4 u0 ~. `

    , R# s% T6 W* `  @# L% e            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    0 A) @2 C5 R! p% ^" k3 d            startx++;
    - A: _8 n; B2 `; x; L0 t( X' T1 B; T3 ]            starty++;. _0 W  P+ e) z$ n8 u6 E8 q6 L
    + Z4 p/ e: Z! u1 f! I$ W, ?
                // offset 控制每一圈里每一条边遍历的长度
    & M! v2 U; c, V; m! N            offset += 1;; {% @, k% y' y) u/ I: T6 W6 X" I4 ~
            }
    1 B2 b5 b  ~+ U: M3 b7 `8 J
      s4 p) m% Z) p0 d" A        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值5 _4 e2 {: F* X1 h
            if (n % 2) {  R; \' j% g& K) O' {1 N5 V
                res[mid][mid] = count;
    7 G: E. g1 T6 ^* J/ D' O        }" A+ i0 T! C/ b* b! J/ z* _* m! [
            return res;
    2 V+ x! c/ t3 M+ o% I9 f    }* Q3 }0 T9 E5 h* {9 l- s0 u8 i6 y
    };
    ' P, r5 H+ O7 i5 l* _
    - w% I( ^, H/ }0 S( Z: F————————————————4 k/ c/ H/ r/ o; g; g: `
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    5 v" U/ F. {7 D8 n原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    ' w  _' ~' G! U4 i9 u6 a1 q1 S$ Y- \" t3 r* _% _

    3 D4 l/ S+ y" {
    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-4-11 00:54 , Processed in 0.485708 second(s), 51 queries .

    回顶部