QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1992|回复: 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
    数据结构之数组练习
    , u4 L6 U+ {& z1.leetcode7049 a9 @  m; Z# ~" q0 c0 P
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。, R6 q2 b# Q  a; e& O4 i

    : S! x& I3 K8 w) X- ^' t/ b题解:升序 数组, V" O9 W  r% `& R
    ' h, i) j2 w% x3 p
    方法:   二分法9 j" t+ n4 f/ \" P! x6 A
    / c3 X& X$ I) ~8 L3 I  U4 y
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)! b3 k6 A' d' d' A

    2 ^' Z  y* U3 b' w6 s: _5 p比较nums[mid]和target的值:
    " w" b7 Y1 H2 `% L" g
    0 `$ P$ g" @0 S  G1 G如果nums=target,则下标i即为要寻找的下标;
    & Y9 y. C4 X1 @6 Z
    . N; ~* Y# s* Q1 o7 T: T如果nums[列]> target,则target 只可能在下标i的左侧;
    & Q$ p% k9 Z9 Q3 E
    0 a  v% a, p& M  m8 J- lclass Solution {
    0 \$ m& n: |. |3 I  Apublic:
    % \4 m4 c2 W: f. P    int search(vector<int>& nums, int target) {
    ' `' N, T) E- G9 }% q/ e% S        //区间[left rigth]
    # k6 u6 C# k3 W8 t# O        int left=0;
    ) x9 \3 [% A9 s# F3 X. M        int right=nums.size()-1;
    + z2 m7 j; F4 Y% B        //结束条件 left>rigth
    + ^& p# u' G0 P+ P0 }3 l! a2 a        while(left<=right)0 j: g9 ?+ X& X  G* `- I
            {4 C& c; J4 @- G
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]  @+ i* B+ `" e5 i6 w7 O
                //[middle+1 right]
    $ I' t3 l1 S" w  y/ Q+ S0 I            if(nums[middle]<target); {. _3 ]+ `$ d1 m
                {: h: C# ~& S( |# u$ A6 i
                    left=middle+1;
    ; q( ^; f1 G+ N4 m7 u            }, I$ Q  W: R+ c
                //[left middle-1]
    ! E( n; n% I3 N8 R, Z            else if(nums[middle]>target). K; N7 v6 ?2 c$ g
                {( o7 {* U+ _+ i( d9 u5 D2 x" u
                    right=middle-1;
    # {! K* F5 }3 X; N  y% P" v            }8 i/ I* R9 h/ z/ W3 q+ a
                else{( @  b7 K8 b& F% N. G9 E
                    return middle;
    7 y  P6 [  _  Y- R" I" X            }) i& F* g7 c' L! ^. E5 b
    7 _0 U- A7 b+ D3 O
            }" b) l: I9 h9 A* f) J. T
            return -1;
    4 Q8 @' x' C) s- q$ x
    & t' t! }% P5 F: O' h$ f* q# N* j    }/ F1 K( _+ \1 l/ u
    };; g/ P! M7 O# t$ t+ Q

    ! p$ ?7 }6 [. D( @& U注意:
    9 ~0 z  f' I8 n% A# D. V! u( m, D# P) ?# L# q8 {: ?$ l) n
    (1)设立区间为[left, right],终止条件为left>rigth
    1 g; d3 W. X1 ~$ b+ c: E+ e  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    $ i4 r: ?8 ^! u  (3)    通过改变区间的左右值;复杂度logn! i6 h" Z0 e! j4 A3 F# D

    & P8 ^7 d, h/ I- R" `2.leetcode 27移除元素/ O/ u" D5 L3 ^: ?0 ^; l
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。* I+ ]0 t+ W( z& c6 r1 Q
    # O( j  u+ c" S( H& n8 L( z
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。8 ]+ Z# W. `6 q  [- z/ L

    8 ?4 p( [. p1 Y# `7 O元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    ) ]% A  b) ~; _* O. n* {: e. n
    3 k% U  O9 ^8 H: w; ?5 j, ?示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    + |2 e. m- l& Q# X+ o2 C- [8 M, f4 b: I3 x+ G, f/ W7 r  D
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    . S4 ^8 y/ y6 o. {7 t+ w( U0 u# J9 c4 C4 P% u$ l1 c7 c; z
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。& l9 o9 Z2 p$ O) o

    ( b5 ?' R3 T+ @$ L2 E* H* Z方法:双指针6 I* ^7 A( J& j' N- a- n: z

    ( R3 s( E* D4 E/ D1 `0 O$ t) T, Lclass Solution {
    ' j- f& \( b9 \) y/ T+ x, j! bpublic:
    # A9 {4 I/ V( x+ b2 ]3 p    int removeElement(vector<int>& nums, int val) {% A0 A) F9 G! H$ n. U
               int solwIndex=0;
    6 P) [. K( q# n8 L# Y* ]+ H7 x           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)5 w1 m% M- ~# B. q# U6 h' X
               {
    3 I0 g2 I: x4 d  L+ T- |* K               if(nums[fastIndex]!=val)
    3 `- [; w3 ?) U* v7 m5 \' K               {1 U+ C" N! y6 d7 z+ X) V& |) O3 k
                       nums[solwIndex++]=nums[fastIndex];: p" R! }5 w7 Y) X' g( g; @7 V
                   }
    " w7 W5 K" t( j7 t" M0 E  Q           }9 [4 F1 }$ L' X2 B& c
               return solwIndex;% P' q3 T* K# X1 v
        }
    - k- M7 v$ U$ f; ]  x' g. {, u};
    4 [3 l1 _/ f5 u- Rsolwindex:用来覆盖0 C' P. H# w7 }

    6 N8 G7 j- c) e* yfastindex:来找删除元素++
    . R5 l3 D  ^6 \9 p! s, ]& G; R2 V. A
    3.有序数组的平方
    ; b& u) Z1 Z* b$ K2 {给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。% j( u8 ~, x9 t5 `4 T3 J
    4 K$ k: U) W% ?) k' O" E$ q
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    # @6 x: q; a- J' D- m
      _* I7 ]' Y% v4 V; I6 p9 I  D那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    ! ]7 k! P5 L9 g* m' y' P+ h% K0 b# n1 y( C+ g: t0 G8 E
    此时可以考虑双指针法了,
      {$ S4 n5 V4 @( X; d: ?: q6 J: @( l' E: V7 Z$ v
    i指向起始位置(负数),j指向终止位置(正数)。1 l1 A* _* c3 r# @! U6 L3 v: N
    % k& h' o% _. \; U0 o1 H
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    6 ]8 [) n  Y, k& O* Q$ ^3 B$ h5 S3 j" ^/ {2 s
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ; C6 V. Z9 |* q9 B+ ?' S( K- }  \- p9 U* R4 w7 J
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    % {  i5 e; B! v$ \/ F# u2 i
    ! V8 M( ]! f5 e2 v$ t$ X# zclass Solution {
    4 B3 E/ ^! u& a* y* mpublic:
    ' J- k3 F, L/ c: s3 H    vector<int> sortedSquares(vector<int>& A) {
    ) ^5 b1 g3 l* F2 e+ C  l) ?3 K& \        int k=A.size()-1;
    $ w. l$ f$ `2 G/ L* L        vector<int> result(A.size(),0);2 o/ Y. N4 O4 I8 a1 f
            for(int i=0,j=A.size()-1;i<=j;)2 a; j( z- b% s, e+ d, d+ W
            {
    & p& J# D/ {; q3 J0 X8 T/ s5 ~! d            //遍历一遍4 y& N) ~1 g! U) _( B
                if(A*A<A[j]*A[j])+ T) s9 h9 k$ y6 ~1 x' W
                {5 {9 u# e0 Q% F+ v0 Y& n  R5 d
                    result[k--]=A[j]*A[j];
    * G) N. U9 X: {) Q  J                j--;( _- ?/ b8 Y% X
                }
    ' X& @: A4 J0 f4 h+ A. L            else
    ! u* X2 \# d. Q+ q9 p# e            {- z% y# j/ w1 e7 E8 N! L
                    result[k--]=A*A;2 c: W5 J% Y( g# I2 x/ m
                    i++;& |( }9 [( v" X" }+ |$ L, I9 f
                }
    & F7 Y6 C6 r. a1 J$ a; n/ G. Q        }
    2 z2 F( `* f5 L0 |        return result;
    * v0 r+ Q8 ~) _1 K+ j8 E
    9 S* D/ x( e* u9 n    }2 y) N3 R$ p" y: ?
    };
    2 ~0 F6 F/ i3 g% u: [( {5 j. r( t
    0 D/ |# v1 }9 g8 c4.长度最小的子数组
    3 ^$ D$ {6 R7 |1 X7 p9 a7 X给定一个含有 n 个正整数的数组和一个正整数 target 。7 w5 }+ |5 c: a/ e/ g
      f; f3 ~2 x7 k* v' T% u% L
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。3 f7 q8 i2 Z8 Q' ^5 M( I& p
    ! U2 z9 [) _; n3 M) g7 X' O9 m% W
    方法:滑动窗口法: u2 X  f$ S0 N8 s4 E9 m

      i' i- m+ s5 c' e) R$ k就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。$ r- P# Y! \1 t( p1 L' k! Y
    6 E3 i) |4 ?7 F  G5 N
    三点重要:. d/ w) g6 r9 F+ }/ F
    ! {* z5 m  a0 \" n( I- L5 y+ M9 n
    窗口内是什么?& O4 i( u4 ?5 Y8 N* T; Q- f4 A
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    0 C5 {& S  N8 N$ |7 y% d" b$ A如何移动窗口的起始位置?  J! f9 c5 q4 ~1 |3 t$ P2 b
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    1 G. T- y# F& z8 i8 a3 W: L* N如何移动窗口的结束位置?9 {, s) c7 {& C
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。7 z$ C! O4 q, X! J

    ) P4 n9 z  D1 _, t# k6 }$ E 代码如下/ n9 f6 b3 J2 z

    & e! _9 A7 L0 C8 d  lclass Solution {
    5 [' F* c  n6 V/ G! T5 F& Vpublic:6 W, t4 J% y' X, d5 D' v3 d. ]* p: Q" p
        int minSubArrayLen(int s, vector<int>& nums) {4 R" r  J% n: f
            int result = INT32_MAX;6 V+ F& q* P+ z, Y: S* s1 ]
            int sum = 0; // 滑动窗口数值之和/ d- U3 @) M' a
            int i = 0; // 滑动窗口起始位置/ z1 o) u1 Y2 e2 N/ P9 w& e% A
            int subLength = 0; // 滑动窗口的长度
      T7 s9 ^" t' i* m- R$ s1 T! \) a) O        for (int j = 0; j < nums.size(); j++) {3 B3 _: Y! {1 C* V* u% D. b! U
                sum += nums[j];7 J9 L; y% a( ?* D
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    7 h  X$ t/ V1 p+ b" A5 s; R* k5 ?- h% T            while (sum >= s) {
    * d* Q7 l5 s6 J  c+ k3 b* s$ ]                subLength = (j - i + 1); // 取子序列的长度
    + b0 n. k$ _. o                result = result < subLength ? result : subLength;//一定会赋值# _' O; d% O! n& e- O% |) ~6 G, i
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)3 d1 g+ `, i6 z/ _+ J1 s
                }
    0 \8 o: y, D9 k2 \3 Y" x, N0 t        }6 ]3 I" R; l) d8 P7 s
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    + x6 g3 h. v3 F' T* u        return result == INT32_MAX ? 0 : result;. c! z- K7 a1 n- [, b& L
        }
    9 y5 _! B6 x2 k, c! D: C6 B! z0 w};: e5 c5 [- i* B1 s

    1 I# a- f7 V, H  J+ A0 y一旦大于,就减去左区间的值; I% O7 i9 e9 ^+ w

    ; @2 B* P5 t! I4 }2 n; O5 L+ w5.最难题螺旋矩阵||
    - T$ T" F7 @& f- v3 i& k模拟顺时针画矩阵的过程:
    ' U4 t9 F, l% [9 s5 r: Q3 x' T
    * H2 G7 v, P, J! I0 I: ^/ Q填充上行从左到右
    9 b8 s) E" z$ b0 ]" G  o$ t填充右列从上到下
    % g  [7 h4 H5 f) W8 X! R填充下行从右到左1 t0 D) O. s& O$ f
    填充左列从下到上
    . x+ M4 `& _. w4 V5 W. y由外向内一圈一圈这么画下去。
    ) w" U% Q2 a4 O! N
    " p& N4 L: O8 s  j" C3 |9 E这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。3 {, ?* T* ?9 V: r+ m( a

    3 x/ L8 Z: ^  x
    4 N2 d+ \* g, R' ^
    : X, G' Q# O8 e( O  l
    6 F- d0 b1 w; {, ~& B$ L& w4 a  G2 u$ H# M2 j# M
    class Solution {
    ; X# K1 X% t% _% Q, Epublic:
    3 r/ Q3 e% F- p) V    vector<vector<int>> generateMatrix(int n) {/ X6 w: a4 E0 d, t& a1 y9 X
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组/ ]; n* Y  }3 O7 b6 R: n
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置, ]4 x7 e( l0 |  q# `* S
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理) g" `8 ?( H% U
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    " C( W8 u  P# R! N        int count = 1; // 用来给矩阵中每一个空格赋值! q6 t: f! z" C0 C! V9 e
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位8 M# K4 W  u0 J/ K( x6 H
            int i,j;5 Q' O0 h. M/ n, [, S# z
            while (loop --) {5 ?0 a/ G- T# E, ]
                i = startx;
    . A. }2 @& C8 j( K            j = starty;
    ! w4 p4 a' p0 K0 @0 j: R+ t. M% G6 O
                // 下面开始的四个for就是模拟转了一圈' Q4 K4 j7 d- ]7 [8 D
                // 模拟填充上行从左到右(左闭右开)
    6 s$ |! R& C' U) b* g8 r            for (j = starty; j < n - offset; j++) {' L% R$ B8 O4 z( p: M: s2 R
                    res[startx][j] = count++;
    + U4 \- j8 r* e3 U5 M& {. w; U# f            }
    ; Y; U0 Y2 x9 l5 |$ h$ w, S            // 模拟填充右列从上到下(左闭右开); ]( m, Z  K" S/ a0 t1 Y0 K7 e0 y
                for (i = startx; i < n - offset; i++) {
    # S$ ]/ @6 }( H5 ~( I1 ]3 f) x                res[j] = count++;' c+ Y7 m3 L$ x- U! R
                }
    $ j. N" C& n2 D$ m            // 模拟填充下行从右到左(左闭右开)6 J! o" H* c3 j! v
                for (; j > starty; j--) {9 a' p' c4 H; a1 \3 p# W- \
                    res[j] = count++;
    0 Y' A7 ?( E6 M: }+ v. g5 Y. b& X            }
    & S; n( n, [" a+ D: o: E5 m            // 模拟填充左列从下到上(左闭右开)/ |0 _% d" e) C( z
                for (; i > startx; i--) {
      i4 U- C6 o6 P* o) L) a                res[j] = count++;' P, v3 i# _/ d" f+ R
                }/ c- p' {5 U5 ^7 e% D6 l

    8 j# z8 F4 X6 x* N3 `  [3 @  l            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)# i3 R/ _; ^( w( |2 [
                startx++;' z2 k& p7 W  u* E2 U. H% H
                starty++;
    + d+ R) w7 s5 ]/ X3 ~; w- K6 y$ Q2 B1 [: o* M0 T8 f
                // offset 控制每一圈里每一条边遍历的长度/ v2 l. u; t4 I1 d) R
                offset += 1;
    ( r3 Z8 Z0 |! `6 \: k- g, H: U        }# d0 s+ T% I6 s( S/ D) f

    3 X7 Y/ |7 w! _2 e$ d        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    ) h& R) X: y3 a+ Z/ T) q1 I3 \# M        if (n % 2) {5 {' |" n+ K2 Z% B* v; _6 x
                res[mid][mid] = count;6 s0 z3 Z- |/ o0 E+ {9 z4 B0 \
            }
    / m% \) C  s& ]) [1 P! r4 B* g        return res;+ t7 y$ y: V  T' T
        }
    / c/ S: Q0 I( `( a: h2 ^4 y8 d};
    2 {- ?' Q( ]' Q) G
    + g# _& S. @& ]* @' H, p: {————————————————' o9 I) |4 x! a# ?
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。- ^! `7 C8 s9 G$ w$ F% a/ r
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039) ]  ]7 X% X4 F/ Y0 b7 P9 W$ k7 @

    / B- t; k; P  ~1 b$ _; |( l
    2 f. j# j3 T8 J0 ^0 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-4-14 15:03 , Processed in 0.582367 second(s), 51 queries .

    回顶部