QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2010|回复: 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
    数据结构之数组练习  M' J5 }4 f$ E6 A$ `
    1.leetcode704
    " `% E8 y* f# p1 n+ Q/ A2 K- t1 e3 d给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    & M; i$ F3 H, x4 K
    6 A' U- z7 A6 }( w1 p+ }题解:升序 数组
    / Y2 a! C8 L- X$ @' p& r9 J: h/ a) O0 q
    方法:   二分法* {  D$ A8 r, e+ |4 M* a" U
    ) R+ h5 |5 B% k0 x/ d6 u; V
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    " V, W+ t" _- z6 Q7 x  ?  g; s/ \, A# w, Y, x3 t
    比较nums[mid]和target的值:7 g7 f: |* g" S' B# @% j8 Z+ R1 V

    ; S2 E9 j5 e0 }8 ?! a1 l  S8 k如果nums=target,则下标i即为要寻找的下标;
    ) S( d, g! O$ M; x+ ^) f
    6 u  O* f  u; L' s' C2 F5 P如果nums[列]> target,则target 只可能在下标i的左侧;, y1 P( Q, {+ e
    5 }6 e7 g: Z7 r1 l
    class Solution {; c# u; r) s7 u8 }  d- j
    public:, R" [* B7 _) d# g# s3 |
        int search(vector<int>& nums, int target) {
    & b& n' E' ]0 y2 B& V% O        //区间[left rigth]' b: ^( ^- B6 R2 [( o, G
            int left=0;7 h6 O8 V3 _& _* H
            int right=nums.size()-1;
    8 h7 z0 M2 [4 t. `6 g        //结束条件 left>rigth9 k0 n3 |, ^( U6 y- r
            while(left<=right)! u& q: W/ |( M1 t2 X* @. K) q! V
            {; u6 {2 F, ^+ B' Q1 H, Y% ?
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    9 c9 N3 Y  o0 \. l- j) l            //[middle+1 right]4 f2 b$ {  C! S: D
                if(nums[middle]<target)! |8 B$ |: c, H9 g8 D$ ?% g, `
                {
    - r9 z* _/ m5 [+ ?: z% e! H8 ?                left=middle+1;% V1 Z, ]( F8 G9 D! t" Q
                }8 `+ Q: D% [7 s) A
                //[left middle-1]
    + |& l: q* y1 _6 i3 S            else if(nums[middle]>target)
    1 m6 U5 G* u; ]1 l+ X            {( V' q5 `# n) W9 H/ \
                    right=middle-1;3 ]( f0 s& T& c. e
                }5 Y" V) k6 a5 \) |. m! M! q
                else{
    8 z( q$ ?& k2 a2 E" _2 @! U, ?                return middle;' j4 t3 m! h9 V; U2 p
                }* @, F+ ?* u7 @/ U

    8 |5 E0 s& Q4 J' Y        }
    7 n) H2 y  h1 }8 D        return -1;! z* _+ ^( H8 a% G# L2 C

    ) |' r. |+ b& r* e, W1 i    }9 y$ {4 ?% Y0 I! i: Y6 I: u
    };& q) e0 C7 e% l4 B" i) h8 F/ N( l

    : Q/ R6 X( T! u6 v5 |注意:
    - }) n+ y  D- A+ }& N( @  {" B
    9 {' o) T  H, Y3 z- e" [# f(1)设立区间为[left, right],终止条件为left>rigth
    5 R! a: A- i9 \: h8 c9 U  (2)   (left + right)/2==int middle = left + ((right - left) / 2)$ [! O4 w& _1 W& x) o; X9 n/ e
      (3)    通过改变区间的左右值;复杂度logn
    . O+ E4 H3 s1 Q3 F+ i! l6 m& J; ?# t" f. W; d2 {% x
    2.leetcode 27移除元素. B7 @8 Q5 `) X: C% a5 [( F
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。" P( v: ^9 R9 M6 b) B+ G

    / j0 q) ~! [% _6 U1 B0 h不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。! t5 n$ b* l$ Q/ [0 C6 x
    & S* c4 b5 N( @
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。# C' i5 m: L" O; g% d
    9 j! s) V* G& p. g
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    6 S/ ~3 r- X7 D
      e0 e' W; }* }3 a: J3 M, G示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    3 S5 r$ r/ @0 y: ]6 {0 S8 K) w; J) T) |# b. e
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    * w2 K7 h% {4 n3 _2 f* c
    ! @* M% _3 b% M0 S7 ~* a6 O方法:双指针6 Y; j8 d$ B/ C  `2 O

    & D6 P! l/ @/ r. wclass Solution {
    / G. B2 ~$ A! v0 i: a+ ^public:, l2 {0 a! Z7 `: e* X- h: y
        int removeElement(vector<int>& nums, int val) {' i, a: z8 R6 M# }4 ^5 U% I1 m
               int solwIndex=0;/ a5 D3 Z! o7 f' `! R* p2 q0 J
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)! Y7 z8 I/ t3 a% z4 n, d; k: @
               {5 n2 U( Q2 e/ d. u- A$ `
                   if(nums[fastIndex]!=val)
    * `! F7 c. K  [               {& l9 l  {5 Y& P) a9 w0 a" P2 [8 b
                       nums[solwIndex++]=nums[fastIndex];* ^/ G% k: I% Z2 ~% W4 i: |
                   }
    1 M& S6 D' |' P5 h  `0 [$ h" P           }
    % h3 ~7 M& q+ A5 Z# d) K           return solwIndex;0 a8 t. L, @2 _8 m0 i
        }
    # a& W' c' c$ I. d- _};. B/ \- D, }$ m. }+ J/ h& x. {
    solwindex:用来覆盖
    , @" E3 L4 F9 m, U
    8 @* Z& _" D6 ]5 D- t  f* ^fastindex:来找删除元素++) I0 Q" {% E9 v2 j' w" q
    # Y- }3 L2 x9 v9 S! h  J' g) [
    3.有序数组的平方  H* i; c' h2 i
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。* W9 f4 b# V% s# D2 R  @/ ~+ K( X; r# e
    * M5 `- j0 u3 I0 E- a! G7 x
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。8 }; S5 F( H4 r8 w7 O

    8 x; o' T; z: h+ K* _; {, O( P- L那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    % c. w2 Z) E8 e* j( Q" Z: J7 Q& @& l$ f1 I2 Z% b
    此时可以考虑双指针法了,
    6 C' e% ?8 ?. L+ G
    8 `( S+ k& U# k' z5 mi指向起始位置(负数),j指向终止位置(正数)。4 N/ I  o+ g& Z- J$ H7 |* f
    ; V, |! y. |, c! @
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。# F& P; K+ p0 a, ]
    : R6 s8 Z, X8 w) p7 ^% w9 N
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。( m+ I. n( H2 e% A/ t+ y5 {

    & E) X5 c3 |/ S2 p9 ^如果A * A >= A[j] * A[j] 那么result[k--] = A * A;/ \2 |, c2 a9 F# \, `

    ; v( ^' t  f+ n  h( R$ S) e, tclass Solution {
    ! @6 z, K1 W& m# _6 jpublic:
    ) X# c: }/ I3 r' I/ V. g    vector<int> sortedSquares(vector<int>& A) {/ Q) k. `$ \( ?4 P$ R' c( x% [
            int k=A.size()-1;
    . F1 O% p, T/ Y        vector<int> result(A.size(),0);- X3 z$ V2 E, |* O5 S
            for(int i=0,j=A.size()-1;i<=j;)/ K8 H% X4 s. F: l) i
            {
    , x. d% l! ?+ B4 G1 o4 k5 F            //遍历一遍; q! f% }1 M( L7 s0 x# E
                if(A*A<A[j]*A[j]); ~6 ?  `7 T6 p" M5 [
                {
    ( R' x4 c2 g& ^3 |- M                result[k--]=A[j]*A[j];
    ; k' s; ^. a1 T* m! j- C/ o                j--;5 e# f8 W# r. W5 z
                }3 e7 Q$ V6 p! V! |6 U' Z5 w
                else$ ^: S& _$ I/ K( N4 v
                {" u, a$ ~# s2 O( T0 ]2 E
                    result[k--]=A*A;& ^2 T1 T: U8 C4 t5 q+ X+ b. I  x# c
                    i++;) @! `. d4 q' x3 @4 A2 P
                }
    7 W5 r/ }5 c  i  r+ U" d, a        }7 S. t* Z' W! D9 y+ _
            return result;
    % d0 i. j7 b/ m3 ^! d" y' t& L7 {* ?' i& q' f
        }
    1 R  f: n" C; d2 @3 V, g};
    : [5 Y5 q2 c0 ^0 G& D( [0 {' t/ u* D
    4.长度最小的子数组
    7 O4 J" ]$ X3 \: M/ ^5 y给定一个含有 n 个正整数的数组和一个正整数 target 。" o. s2 u! R: {* t# M
    " P& Y0 h( `, D! U4 ^0 o( _
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    1 u  {& L. v& s
    . b/ E7 w& {: ]" v2 ~3 Z方法:滑动窗口法
    3 c0 h! _) Q6 K4 v$ n* n1 P0 E" R0 `% h4 ?4 r% S5 x
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。8 D- h8 J. }) x8 b7 ?" z; v
    9 X& ?$ t7 Z% i9 y* l7 t1 x2 K' I
    三点重要:
      x7 C& Y2 ~7 H* R, a0 G
    % ~$ |6 T  Q: g3 P窗口内是什么?: f) X5 J6 ?8 B( j: {& X0 R
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    ' }* U7 R( U. V  Z* ]. N如何移动窗口的起始位置?
    2 e9 }5 e* B% U" z" `窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了4 n3 U- d5 {, E. D* l
    如何移动窗口的结束位置?3 p! [3 O1 Z+ t% ^* j$ H
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    5 ~. {: c" g$ G) f3 Z' ]) f* Y2 ?3 d5 V7 o" M5 Z. K* F4 P
    代码如下
    ; x  z4 l8 d. E! ~, |3 ]9 o: u
    # G0 T5 t( j/ R1 E5 @class Solution {
    - d" Q$ n- o" Z7 ^, P* @public:
    & u! m, K+ S1 M    int minSubArrayLen(int s, vector<int>& nums) {
    # j# x% o" e. W! M1 L        int result = INT32_MAX;
    1 ]  j# K% G  z; y; F        int sum = 0; // 滑动窗口数值之和
    4 ^1 }/ J1 w2 R( V6 J+ _0 J        int i = 0; // 滑动窗口起始位置3 t6 O; V- b' K: U* v; V
            int subLength = 0; // 滑动窗口的长度
    $ s* G- ]" Q2 H! @" e7 Q4 v        for (int j = 0; j < nums.size(); j++) {# ]5 x2 s6 F3 [! b/ y' s# l
                sum += nums[j];
      S' A7 _& q) j5 K, j& Q1 p            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    7 n  o/ ?$ N8 w) Z. V  j9 g            while (sum >= s) {  p( U" G, S, {2 }, i
                    subLength = (j - i + 1); // 取子序列的长度4 n; ]! x4 b# f/ m
                    result = result < subLength ? result : subLength;//一定会赋值! X( E1 G) L: J' g2 x
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    + C0 L: y2 P& b! Z  W. [4 V- i            }
    ' {! N: a3 O! ?. {: K        }
    / P6 C& ^4 w" r; v: w        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列4 U8 f' _4 ]2 ?( X5 r- A
            return result == INT32_MAX ? 0 : result;1 w, A- p8 M- ^6 D
        }; T4 l! \/ S, r# ^/ o
    };
    0 D- Y7 F- E2 v4 t+ u! K$ E) N6 o: s0 J* m. c
    一旦大于,就减去左区间的值8 Z' j" k3 P" v- l$ j
    / W; w* j4 V, Z6 o/ t
    5.最难题螺旋矩阵||2 f' c8 h0 g8 T) X: E  U0 ~, d
    模拟顺时针画矩阵的过程:9 |2 @! i# A; t8 ]0 G# _) c

    5 ~7 V1 K, a: f! U9 `, H填充上行从左到右0 t8 n# X, n( B* Q& c* `
    填充右列从上到下
    6 r. c8 m9 `; p) c* v填充下行从右到左
    5 u1 g. [+ ^; ?) q填充左列从下到上& L% E8 N: F$ I1 ~
    由外向内一圈一圈这么画下去。2 p' P; B# T/ I/ _3 B

    7 f. z- _+ L( z' I0 Y4 t$ m9 ~# \" K这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。5 i% [9 q2 \& p
    # F! Q3 H6 v1 ^* b) X9 {

    ( ?5 d* M! Z( [( S" P% o
    , g) J+ Q( j- L0 P& o: d0 e* N3 b* }7 ]! `
    : H& `  m! T6 m! B7 Z  y  _
    class Solution {
    2 S: M( l9 ?1 e7 E( N  tpublic:7 y) [# i  j( v# Z* u* ]  ^: ?
        vector<vector<int>> generateMatrix(int n) {% ?8 [8 q: F" Q2 ?, n. l
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组9 i- {- N2 X' [3 r/ s$ A
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置( {2 f& f/ t$ {% D) e
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理9 q5 s9 T' I6 r" z0 L
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)& Y9 n) ?  K: q, K; n
            int count = 1; // 用来给矩阵中每一个空格赋值
    5 a1 U" z+ L9 Q8 T( J* M        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    $ s3 ^; U  m! K8 g: t6 Q* S        int i,j;
    2 h9 R  s, {+ C6 a% a( t! a6 f- G        while (loop --) {+ q2 G. ^( p! F; B3 Z
                i = startx;1 d+ k  B2 V5 c
                j = starty;8 g' J) y1 r$ n8 O
    * `# i: f% ]- y! J$ G: X
                // 下面开始的四个for就是模拟转了一圈
    ! o" m* `, g2 F            // 模拟填充上行从左到右(左闭右开)! I5 [  B0 y+ m. s' E+ X
                for (j = starty; j < n - offset; j++) {( H. k% F+ T# p$ K
                    res[startx][j] = count++;
      F+ m# y( K+ y  d            }2 m8 ^/ W" w# V3 \$ q; e/ Y
                // 模拟填充右列从上到下(左闭右开)9 Y& k7 i( X3 f' q- `: Z+ A4 T
                for (i = startx; i < n - offset; i++) {! G2 _6 N# L+ \  E& W
                    res[j] = count++;
    2 G' T0 O% E( @1 v5 u            }" }; k! _% e- l/ D# k7 d# ~' Y
                // 模拟填充下行从右到左(左闭右开)
    7 p$ R0 g  d; E7 y            for (; j > starty; j--) {) z; v  W/ B* z8 [
                    res[j] = count++;
    + m; V0 c6 q+ r- G8 }4 _: B* I            }
    : R; `8 f+ j! G4 I2 ~+ V$ l            // 模拟填充左列从下到上(左闭右开)
    ; t  ?5 m! E) v/ N            for (; i > startx; i--) {/ @; W8 c7 @0 C/ o
                    res[j] = count++;/ L# s( r* x& |- c' B# Q, Q
                }7 L/ a- X& l$ _
    5 i- `2 K0 s& t. w
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    1 [4 t2 A3 [. R* ]            startx++;
    , P4 e) h* B* W# M6 A: D( m            starty++;
    # V) {2 e+ |& ]$ h& h  p: A( J4 r  t- A) D) C0 P3 a
                // offset 控制每一圈里每一条边遍历的长度
    ) u5 W# c# y$ Q            offset += 1;- v/ Q2 P7 r8 f0 i
            }
    ) o9 V6 S7 ]. h  X
    & {- p( G- B  `        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    ' X1 F1 ]7 z. n" }+ R9 `5 L        if (n % 2) {
    5 U. Z6 i8 |1 e- m7 G$ g            res[mid][mid] = count;
    2 V% I- `* N4 \        }
    4 x2 v9 ?' |. \$ y! v$ Z4 q+ k5 s! D        return res;
    5 R0 U/ m" |, m% H9 }/ Y, p    }3 c- U" k; R( U' @- [. \3 _
    };& _6 d# z- C$ T! Q  y

    3 _4 G$ m$ H% p# I; l% c————————————————7 X$ v, D, T( h/ u/ Y
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    6 R* v- I: o& B; o, k原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039) N4 }( I& c& B. v& ^7 i3 U
    9 _# }# ]6 E$ [& u5 E  E% A& z

    7 S; m# H. r7 D
    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-28 10:38 , Processed in 0.451883 second(s), 51 queries .

    回顶部