QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2038|回复: 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
    数据结构之数组练习
    + z( A# @' z" a$ x+ M. k1.leetcode704
    5 ~5 L2 o. @" r. g# a2 g$ A给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。; Y! z0 o5 c$ [# y/ j, y3 D

    6 u. c8 {; d2 M5 X; h; T题解:升序 数组) `  M2 D1 k8 N0 t
    : p) s& o% d6 p: }& C
    方法:   二分法+ |1 R* O4 a0 t0 G6 }' [
    7 v. L. Q  o: t: B0 k
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    ) g9 Q; x0 J/ X- H1 _9 E0 k
    2 Z% ^) N: Z7 }# d& p! _# F8 F比较nums[mid]和target的值:* J& F( o3 R% `- a4 k8 q2 g1 B- E
    : z/ v$ f1 E% z
    如果nums=target,则下标i即为要寻找的下标;* u" U5 F4 u2 Z3 q% V

    " A' k4 \. a& n* `; s3 i如果nums[列]> target,则target 只可能在下标i的左侧;7 d" @/ P0 Z8 T' L3 S/ P+ L5 T- Z
    & E# |, W2 j7 u1 W7 m+ Q2 q4 g
    class Solution {
    9 ~. r0 Y2 R& Qpublic:
    7 n8 W1 ?8 n4 Y& ~( O7 M: u    int search(vector<int>& nums, int target) {
    9 o" V8 U6 z4 d( Y        //区间[left rigth]
    / d$ A: f! W. L! G2 ~        int left=0;
    $ }# S, E# I' y& |$ U        int right=nums.size()-1;
    ' V; Q$ k; F5 |% c7 b        //结束条件 left>rigth- E! w2 d0 v, N( {. [
            while(left<=right)  N$ c- q' a3 b- |. J  S! g1 S* n
            {5 t2 l( N  f# E
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]# \5 M2 R8 }8 f( {6 z$ z
                //[middle+1 right]
    4 }* d6 Y) U% e% u8 p            if(nums[middle]<target)
    0 s5 {1 v9 T6 r$ G. A: ^7 y            {( ~4 e- A7 p$ k, M6 }
                    left=middle+1;. p3 Y" [+ K$ G" S) N2 c
                }2 R. R% \2 L5 U3 m* x# E& g) l
                //[left middle-1]
    5 V. ?# v7 `, Q4 g! {, k: ~            else if(nums[middle]>target)
    " v1 ~6 Y  y+ U2 ]0 ?            {
    2 `: w( k6 y7 Y3 r) w9 T& C                right=middle-1;
    ! F- A8 S, q. y- H4 T( k2 s7 g            }
    + Z& S6 ~7 W/ g5 z/ q- O+ w            else{; q& b7 z! k/ H
                    return middle;
    " @. P1 ]8 y: [, t8 L; \            }
    , }9 N, j. [# Q9 F# C( n& j2 ^0 v+ [2 ~- ^9 r2 V2 z9 E
            }
    2 ]* j1 [7 B0 e$ U9 W        return -1;
    7 L: l1 d2 T4 _, b. |" \  y
    3 n4 }' L. H3 t& O    }
    7 t) `7 A+ }6 h. N- z};  Z2 X. f, h, q  q; M. j

    # Z4 e3 W; k: i4 r; K+ @- w0 Y% I注意:
    , R2 Q1 _: m4 u9 t4 E, k- k2 J2 q7 \8 k% j$ p
    (1)设立区间为[left, right],终止条件为left>rigth
    8 E/ C1 `) Z1 v  `& h; w  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    & R4 k4 Z& e5 S. P9 O3 E  J  (3)    通过改变区间的左右值;复杂度logn
    - t' D9 K2 n% @' z8 W
    7 a2 n4 ?& J( T1 d5 {2.leetcode 27移除元素
    ( n$ ?6 s( B: j# P# d给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。( d2 c' e, H" d

    ; Y( n: U3 g, {+ C: L不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。5 C% A4 N& g% A/ ^

    4 b2 W* q" e2 |+ {$ n' r; r+ w元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    , H" x4 N5 r8 [% }& o( C; u9 p* r# V
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    ) S- L3 ~, C/ B1 `7 N& h' B% g+ V/ P2 T) i
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    + L9 f7 U: g7 a  p( v9 F1 ~5 D# a, f' j( b
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    $ c  O3 x7 t* C  l
    2 R0 F; m8 |) B2 u& n方法:双指针
    # y: I5 g$ Y1 g( W- q
    ( i. t: {  z+ e5 fclass Solution {
    * B5 }' v& U, {; Epublic:
    : c: L- F9 w, z' c    int removeElement(vector<int>& nums, int val) {
    % y3 W1 {1 B+ ?% X9 o1 [+ J, n5 c           int solwIndex=0;
    ' m8 o% ]( d  c3 Y; r0 O2 h           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++); U" d8 y; t" P; N
               {
    0 g2 Z- _3 @. X/ f, `- ^               if(nums[fastIndex]!=val); c$ e) n  h! C3 s
                   {
    0 C& k1 l3 J8 M- _! V5 }' d                   nums[solwIndex++]=nums[fastIndex];) i7 r5 \- R) x& P$ |
                   }  n, o, r' a& E9 d% Z5 ?3 ?
               }
    7 }5 `, T# N, ~+ y' O( C           return solwIndex;2 ?& v2 i$ |; N  G) _
        }) X7 [- H; E* w
    };
    * m, ?3 l( E6 p# [solwindex:用来覆盖
      _# P4 }1 m# G( b% g
    4 ]1 p  {7 Y& C+ i. Hfastindex:来找删除元素++/ u3 b0 j; N7 P5 t2 i

    2 R: U/ H4 k* P8 `8 k5 r! L& P' S( k9 k3.有序数组的平方
    . m% w0 k; R- h8 X给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。* x* _) \" O- T3 C* I+ u: s

    % K# q: ?/ [- `数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    5 s0 a( W. U) ?2 i+ F/ {. n& U3 d! b1 z9 A: |0 {  V3 u" d  s- N$ y
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。5 y8 [4 m6 a. |( D

    , t# \5 L' k5 h4 T* v此时可以考虑双指针法了,
    ) O; \' P5 d% S7 B/ L% w) H1 b
    & J  o4 u* F% T- oi指向起始位置(负数),j指向终止位置(正数)。
    3 z' I  C2 h6 f; j* r6 g4 D* K  o+ U2 j* N7 ^0 {
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。3 N# f0 }" y6 D

    $ D, G1 a1 e- H% q9 P+ q* s, g; Y如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    1 G6 `4 e& s" E
    9 ^8 v  J5 P- W! `如果A * A >= A[j] * A[j] 那么result[k--] = A * A;" |9 H  X$ Y- [
    6 e& B" r" O" r) ~& W0 F/ V3 M
    class Solution {8 ?- m5 P9 y# v0 [3 y2 c! Z
    public:" U# G/ }9 \9 E2 n- f! a1 X
        vector<int> sortedSquares(vector<int>& A) {
    : L( a( `" V& N( p2 {, e        int k=A.size()-1;
    . u  F" \, h( t& l        vector<int> result(A.size(),0);& j: I% N. }  X! K9 w. K' P
            for(int i=0,j=A.size()-1;i<=j;): z8 Y% Y' ?; d: ]5 d% \
            {4 L( M& c7 u& Y* W: M0 p+ c
                //遍历一遍8 G8 q2 x7 m/ Q4 q
                if(A*A<A[j]*A[j])
    " u5 M+ O7 i( I            {
    ( ?. X/ i  L5 h, z0 h                result[k--]=A[j]*A[j];. ~/ ^: y0 R7 R/ W2 q* z
                    j--;
    3 Y& V! @  H  R% i  S  M            }# V3 s8 J9 r1 L$ M. H
                else) b" l+ a2 j* D( k5 i" m8 O
                {
    $ O; B6 V* D( k: S2 A+ I8 K8 L                result[k--]=A*A;- F( u5 I3 Q- }8 g
                    i++;
    ' q- h+ s4 _. \* Z# b# D            }% R& A6 S( n* m) \( c
            }
    5 k1 g) w4 f5 Z6 l3 Z        return result;: \, S9 [" _1 K& O! Q3 o1 W

    % o  d5 q9 a' H2 F& B# _    }
    4 @2 i$ E3 J; d};
    : ~2 f( L: f, i: r1 I% R3 U$ k* Z- J0 O
    4.长度最小的子数组/ J3 x$ H4 f9 h* ]: Z+ n
    给定一个含有 n 个正整数的数组和一个正整数 target 。. Q$ ]# b$ `& _0 Y- Y+ g

    - r  v7 J+ U1 k2 P找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。: ~& u. e6 n  @8 P. |
    8 n; y3 z/ k. u( Q5 p( @
    方法:滑动窗口法, u& ~/ p# P1 r4 d7 H- `
      S1 q5 h# R0 E# w+ p+ ^. M  w
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    ' N4 ]8 E7 w: G& k8 }( P- O* [$ c. N: G9 F8 v4 r" U/ D) U
    三点重要:! M% p( Z  D- T& \. O9 P. t$ f

    2 I7 q. \+ S6 |窗口内是什么?3 g  a3 x  A- Y# d0 _
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    ) ^% R: B3 U% b$ _. [6 j如何移动窗口的起始位置?
    * O8 l2 _7 T5 W窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了& Z" ^! B1 d% |; j: m* {
    如何移动窗口的结束位置?; {  [/ C- J% h' b6 H+ `6 p
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    ' A) _  D: e; X! J4 Q9 {" f8 j1 O
    代码如下# q' q( c3 k5 z0 p

    ! _" L, F6 m% i8 {) b' Xclass Solution {
    : }% O& T& F9 }" h% jpublic:
    9 w: t' v* _2 @8 a3 x% T    int minSubArrayLen(int s, vector<int>& nums) {
    ) G# f" r2 i+ N6 S2 F2 e' u        int result = INT32_MAX;6 B3 H# @# Z1 o& Q% @
            int sum = 0; // 滑动窗口数值之和
    1 c4 |7 O% f% O, R. {: O. i        int i = 0; // 滑动窗口起始位置& @+ m; l4 m9 {
            int subLength = 0; // 滑动窗口的长度. ]2 l0 D/ ]& U6 ]% |
            for (int j = 0; j < nums.size(); j++) {5 [4 I* f3 Y4 r. D6 y
                sum += nums[j];3 k. n8 @) F0 A( b
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件+ L7 Q7 m- o1 H! T/ d& k
                while (sum >= s) {
    + u' _) ]3 ?4 x                subLength = (j - i + 1); // 取子序列的长度
    " M* q) I  m- I+ N1 g& A( L                result = result < subLength ? result : subLength;//一定会赋值* s2 R; M0 F$ `) z
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)0 Z) K) o0 x' Y- P1 Z. |: J
                }
    * ]: I5 h+ I$ \; M4 S        }
    ! B# X% g" c4 ^2 u. ^: J        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    , l1 W' E$ T6 b1 F3 C        return result == INT32_MAX ? 0 : result;& t! O  L) {' i( u2 a
        }8 R: N5 m9 G& I4 n0 E' q
    };3 D- r9 i0 c1 v/ p

    ' H  T( @" \/ T) h一旦大于,就减去左区间的值/ A- D+ g( S- w
    " ?4 n9 D" W. ^  O+ B0 K
    5.最难题螺旋矩阵||
    / x6 e: B3 W' H7 ^- l模拟顺时针画矩阵的过程:
    2 }. t) H7 f% c" ~# l& b
    ( o; b! A! O9 ^2 s填充上行从左到右
    + S6 h+ v% f/ W/ r( G1 x填充右列从上到下0 X  F, o' B6 w7 I; h* ]; w
    填充下行从右到左
    4 z, E: ?$ c/ Q3 E, V填充左列从下到上; K6 U; V& ^( M# d2 n5 N, W
    由外向内一圈一圈这么画下去。: i; r7 f& p: U7 j5 z
    % e5 L' p! P9 k5 m/ N) L3 B
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    . L$ E! d; f7 P/ l5 S0 d1 f  M1 s
    0 @  a4 n( k/ R8 K! ~( g

    " A+ X1 c) Q3 E9 c
      s" e$ K: p2 U6 y$ ?9 A% r/ i4 q2 ^" t
    class Solution {
    % \0 `, `, n7 K( o7 S* g/ ?public:
    5 S0 H+ X  c* G; U% B    vector<vector<int>> generateMatrix(int n) {
    , Q2 J+ W9 u7 B: _        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组1 s2 W! r! T. {5 B- [* u
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置% H% l  u" V9 }- l; J/ T8 q4 f  b
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理# D# \" k  C# G/ Y, o$ J1 e! J
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    + \! C. |6 Z, S" d# H6 k        int count = 1; // 用来给矩阵中每一个空格赋值
    ; j/ L7 G3 O: \6 D( S, a        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位/ Q5 [/ G2 G# V  ~3 t3 p
            int i,j;  Z8 b5 {8 _! @4 |3 O
            while (loop --) {
    ! }" |, ]/ P: @; Q+ V# E7 R5 O            i = startx;
    # N6 }0 z: u/ P5 R            j = starty;; p/ ^$ _0 L) h& I, C, i- z* o3 x# p
    $ L& C% H( A& K) }  w9 X
                // 下面开始的四个for就是模拟转了一圈
    8 j- Q# I/ s. G: y+ ~1 X$ v* W  r            // 模拟填充上行从左到右(左闭右开)) `3 Q4 s0 V. m9 p
                for (j = starty; j < n - offset; j++) {
    8 ~0 m" G$ M- ?, x. f0 {7 M                res[startx][j] = count++;" K4 {" M5 k8 p- s2 H0 l- K" G3 Q
                }
    ' I, f7 R9 |3 r7 h- w8 M            // 模拟填充右列从上到下(左闭右开)
    / ~# i' h2 p" Q& w. C9 s            for (i = startx; i < n - offset; i++) {
    8 q6 p6 p5 r' V8 [- A$ F                res[j] = count++;
    0 y$ @& J( P# ^. x; q3 r5 h            }
      H0 B( Y: x8 Y6 Z; K; n" |% G            // 模拟填充下行从右到左(左闭右开)
    $ v( O5 `6 q9 X' f- W            for (; j > starty; j--) {
    2 ~% E4 n8 K, ~2 Y: A                res[j] = count++;
    $ x! N( L( X& F            }, I3 V- U" q  \/ P' j) J
                // 模拟填充左列从下到上(左闭右开)
    ( J6 U. M# F5 T; k3 k            for (; i > startx; i--) {
      d, E5 ]- B5 N                res[j] = count++;( |' z1 h5 {5 Q3 r
                }
    : Q0 \! \2 Q0 ~# m5 J; B
    + _8 |; M7 P; ^' j4 ^  u3 W( }/ \            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    9 E, f+ j7 _6 J* f: N0 X6 G- q$ u            startx++;
    : a" R& H3 {+ ^+ X! N4 q: R            starty++;9 \7 t7 ^0 S) V, G

    7 }+ u# z0 g4 C: m8 R  Q+ B% w            // offset 控制每一圈里每一条边遍历的长度$ h4 l, Y* b! ~8 l5 W+ V+ b
                offset += 1;( ~4 \! O6 g7 r& J" h( Y! `
            }3 P$ P7 r! K  o8 @, u# c" `" C
    1 {. l8 p" X" o& z
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值, W9 |. A9 t" b8 u  w5 n+ @
            if (n % 2) {! a0 d9 z4 S( W* e
                res[mid][mid] = count;: K" W+ x8 n4 w$ K# C
            }- e4 C+ O3 t- A. O" Z3 _" S0 E
            return res;
    & r$ B: x5 i+ V, I8 D& j# D/ Y2 S    }8 [* A  w) V- a8 R9 R. n. H; @* v& a; w
    };% S9 e2 x" g) x- @7 a
    % D3 ]5 m" _, ]  R, G2 s4 v7 L' o6 T& ?
    ————————————————& _! e# h4 \% e  m" \; ]. T. Z: z
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。6 F1 P0 Z, _: b. b, K) z7 @: |8 R
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    / f2 k8 K$ I  y$ r5 Q: \* e3 U, X) f. W; l& ~

    ( H) l- m  g- V( k4 Z
    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 02:14 , Processed in 0.410359 second(s), 51 queries .

    回顶部