QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1996|回复: 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
    数据结构之数组练习
    ; D8 L+ F  M, ?4 c1.leetcode704, P$ `# c5 u' G( P
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。8 f, O# a6 _8 v* T& t. }, r9 w
    ) Q2 o3 k5 x  |: _3 R. E
    题解:升序 数组
    2 |- v$ v& K: s' i5 X/ m5 A+ t3 Y: g) D
    方法:   二分法
    . F0 o* c) Z* D$ N; |% r, r; Q6 L& U3 t/ ^# M+ D' y
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    " Q6 A3 o7 n4 m0 C6 E! S3 r# ?
    3 Z' u2 B0 @% G. @) }( ^6 O8 y/ z  J比较nums[mid]和target的值:' _( ]$ |4 h* ?/ n% H6 r. M

    8 b5 Q' Q/ L" U' _7 k$ H如果nums=target,则下标i即为要寻找的下标;5 F$ I' ?; a9 ?' E3 i4 D. O% o& K
    / A; k- S$ _' b: D
    如果nums[列]> target,则target 只可能在下标i的左侧;
    " y+ _  f3 O' l# |% _# l- S4 b( Z" _+ r* J0 u0 X5 ~
    class Solution {
    ' E/ _8 x/ r$ J9 h% q5 A7 c2 E1 Dpublic:
    7 l& F; s( s! _/ }( _. {8 A( f    int search(vector<int>& nums, int target) {
    0 N7 Z2 j/ V% Q+ l5 H3 n. W        //区间[left rigth]% Z) y. V. k3 _# }
            int left=0;+ q  R% L/ o! H. w" h. E
            int right=nums.size()-1;4 m) Q% }- {7 L
            //结束条件 left>rigth# x0 ?: a. U  d8 M: r
            while(left<=right): ]- v6 R; Z& V6 G6 I- k
            {# ?$ q. \% T; K  D) V0 o% N
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    : g& w4 ?- x4 M. V  m            //[middle+1 right]
    0 w* F0 L0 r% m* g            if(nums[middle]<target)" q5 l6 H. G. [
                {* f8 d6 _+ [7 q$ C
                    left=middle+1;7 w4 o5 s2 R: V: X
                }' Y$ ^; O: S# J
                //[left middle-1]0 @2 l' s+ k& ~
                else if(nums[middle]>target)- G# @5 H3 g' V9 \
                {$ R1 o, [4 K  Z; }$ D3 A# @
                    right=middle-1;8 F) I4 c4 e% H( y8 z/ G
                }, R& u# g, s! f, R5 ^: L
                else{
      G) h0 f( D! D; p5 L5 z9 k. r                return middle;
    3 N$ a" f( F& K' ^4 s: ~( K            }
    ( ]( Y% w  M4 ]; B3 |  w1 g
    % U0 K+ A3 ^4 P4 Q  M' t) o        }
    1 A6 S2 ?) b5 v! `+ x8 p2 H        return -1;0 a5 B9 t( L+ u9 G

    5 D2 v7 `$ a1 ~; d, F" d    }
    " z/ ^* a; V6 J/ A5 X8 K};# v3 c5 h9 S) O4 B) Q( {

    $ L4 r7 C: a6 f. K8 O注意:, e' F( k2 F0 q) g
    9 n1 G/ I& V7 B* B! g- I9 u
    (1)设立区间为[left, right],终止条件为left>rigth1 w: B' v1 C4 j2 z& ^% |  z( l
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)) F7 z8 J, I: q) Q3 l. f1 j% L
      (3)    通过改变区间的左右值;复杂度logn  ^- n: T" U' N
    6 u* U' D/ ]6 g5 c2 O
    2.leetcode 27移除元素+ x$ j1 V( O. Z4 E4 l9 {8 S5 ^. D
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    4 E9 g% G6 a4 ?- o2 n; |, y: F6 a/ g# u" r: o$ j
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。( `3 d' E4 m/ l: s

    + |. a* ^, a' \' d; g: x元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。; k5 J: P$ c$ p' u2 j7 x+ x( z
    ' ^1 D2 ]3 e4 B
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。: Z* ^2 [" R0 i/ \9 N" z1 Z
    # H: P, t+ ?. w3 Y
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。; [" @" i, _( \7 w, F' q

    : D8 r* u: N7 M思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    7 l9 P$ G; y5 h, m# G
    " ~' m3 X  Y0 G; q% ]方法:双指针+ t; v  o# W5 ~

    4 |% A- s& Q6 V) ]* }7 y- v# b# K7 Hclass Solution {
    9 G4 G: }% v7 m. b" I& Qpublic:, m. i5 N; r  P" a# u+ y% N5 N" _4 E
        int removeElement(vector<int>& nums, int val) {
    2 T9 a+ Q' o- L4 L& w! ~5 T           int solwIndex=0;
    ) y/ _$ t  N2 O: T! M$ V1 K  l/ q           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)& o1 B) q: C; Y4 x
               {
    + j' M% t) t, Q$ w9 d# Q! g               if(nums[fastIndex]!=val)
      [2 C+ }; G+ r) j0 R! B$ ?2 p& ^               {8 d: r2 ^0 l' I7 C" }0 t& S) s: h5 T
                       nums[solwIndex++]=nums[fastIndex];
    0 ?( l. y% x2 |               }8 a  a" S1 W0 \. R# h4 @6 f3 r
               }
    1 {( M+ D$ p9 W* l           return solwIndex;! V, ~0 \) k# V! t3 Z6 c; X5 s
        }
    ' \% j2 F; O$ V. z! g$ {& ]};
    7 O0 L; l& o! S0 ~8 m; ]- F. Dsolwindex:用来覆盖
    4 K, a5 B( U0 F8 B2 q
    : s# q* ]7 r0 N5 qfastindex:来找删除元素++
    - y. ]  p6 L5 ^! a% h& Y( Q, i. i) x! ]% B% v: ^1 J) G9 ~- C0 O
    3.有序数组的平方: [) c0 h& _- E" |* U& Q
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。: b6 c  \5 x- D  K4 Q
    # H; i% X; o$ k. S5 S
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    + F$ f+ k/ G# Q$ f! A. x
    - j! C1 n2 |# }& q% F* ]! X* Z那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。5 G& T$ c2 v2 b

    ; I$ L* S5 q; C* y% F" C+ `. e此时可以考虑双指针法了,: H- f# u$ e- Y" J7 _

    , z  g( t; F+ Wi指向起始位置(负数),j指向终止位置(正数)。$ z* [5 R3 ^: K# d: f9 e# k

    1 S/ T+ F  Y* {- c- u定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    1 H# Y( s. d" S$ D$ A. D# e( j6 y& z
    5 U0 B* }' [3 q3 ^如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。- e$ M# ]- u4 }! a) M$ q' f
    4 [# i4 W) x& S: b6 W9 P2 }5 d9 x
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    ( G* z' a2 {0 W. |
    , a9 C. I+ m8 I: K/ [$ `class Solution {
      Z# S7 l1 H) w* npublic:
    . r' k+ l0 ]" E    vector<int> sortedSquares(vector<int>& A) {* D# `, U% l0 s& }  Q* o5 H" v4 Y. _
            int k=A.size()-1;2 R9 ?3 O+ p7 N
            vector<int> result(A.size(),0);
    ( f0 L% K0 O2 m$ z$ v        for(int i=0,j=A.size()-1;i<=j;)9 H5 q7 ]" G/ J# ?# j' g
            {
    ; H9 s3 A+ l) \* H1 m1 J6 c            //遍历一遍
    $ `* f) N5 b5 k            if(A*A<A[j]*A[j])- r; w, G* j0 f& z
                {
    9 _6 x: [) J' |1 S+ j                result[k--]=A[j]*A[j];
    " f3 V: ~, B7 B: Z$ _+ v                j--;
    : y4 j$ V) t4 U' a            }
    ( c; l2 r, X. L7 A0 G! l1 V! g            else
    ' G7 e: q0 d' I7 w( t            {
    1 R" q5 U( U* ^/ B                result[k--]=A*A;7 Y, E- \- Q3 |0 C! z5 J: N$ U' C
                    i++;2 _. G' r- Y2 N
                }
    " b- [! t; p# f/ y$ j! ]$ w        }
    8 {& t' F: r' @0 a0 K7 e/ g4 Z        return result;8 G  \& L0 \, [( i, O/ }

    ; o' p- s2 E: O2 y& w: n    }
    3 M8 p! q5 z$ ]9 U( f1 q7 p5 a2 \};) B& @$ m) H- L; x0 g: @3 M& |+ G3 i

    % O* J: W$ q# V, A! ^- a4.长度最小的子数组
    0 k% H+ q& ]: N9 `& x给定一个含有 n 个正整数的数组和一个正整数 target 。
    ) n( n% ~6 G5 Q1 f) K/ t6 x4 g' l8 Y! R' h- j0 z
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。* G3 {" S: Y1 ~8 n
    , y- X9 l7 ^1 c# E8 [% K. r. s$ |) V
    方法:滑动窗口法
    * J6 k6 `+ y' w: ^" D# F, T+ S# i  \1 C( k6 Y
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    " Z. b3 ~; m( M) q% g7 \4 P, H
    0 b- O/ P. ?$ W三点重要:
    6 y" d# a% h3 p6 c% ]* ]1 Z$ P: D- D* o2 H5 k' U
    窗口内是什么?/ Q( {& d, L! S9 l( J" H& |
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    * S' N. P8 }; u" U. \如何移动窗口的起始位置?
    + x  l/ H- A  c. y窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    " r/ i+ L% P  C9 P/ g; }如何移动窗口的结束位置?2 r( S8 _/ C6 e* N
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    / {7 g' R  [. }  Z
    ' ?' D$ R( p2 h- W: s 代码如下
    ( b; t, J" A, s: H, Y4 M* a; L1 I& }9 C1 c1 d
    class Solution {6 M! N3 t( v+ J$ y4 ?
    public:
    7 F7 c# ]' w; K    int minSubArrayLen(int s, vector<int>& nums) {
    . X/ G! R. m; R        int result = INT32_MAX;" A2 a2 p7 ^( u
            int sum = 0; // 滑动窗口数值之和
    5 f  |  l5 W* w" g: _$ e- ^" Y        int i = 0; // 滑动窗口起始位置9 ?' L- X0 U5 F' P3 Q8 W
            int subLength = 0; // 滑动窗口的长度6 G6 s" |$ \- M, {
            for (int j = 0; j < nums.size(); j++) {
    $ h% ~3 v8 r! y5 J            sum += nums[j];( A$ v9 q) N3 v9 N( X
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件" v/ u6 _$ V: v$ Q% M! _
                while (sum >= s) {
    $ a+ j) \# X6 N0 j0 A                subLength = (j - i + 1); // 取子序列的长度
    / q& y: ]1 P+ ?6 H/ ^4 U8 r                result = result < subLength ? result : subLength;//一定会赋值
    8 s+ h) V8 g" ?: Q% z: y) w                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    # f0 x- }/ Y; e4 y1 w( _# O            }* b! M' P* u: ^# P2 U' Y" ~
            }5 J8 ?  W) R1 ^
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
      H* z5 j' r( R& ?- G& \5 \# v        return result == INT32_MAX ? 0 : result;. _9 n" e" F7 m1 d+ y$ V7 K
        }5 E9 ^" t4 _, ?" Q
    };3 z* _) u* t! @
    2 @3 |( a6 z1 P/ D" r# o1 u
    一旦大于,就减去左区间的值. ^7 A* L; \9 d3 L

    # I( i, r. k+ E3 [# ^5.最难题螺旋矩阵||
    * U% Q3 l7 g- W4 a8 Y模拟顺时针画矩阵的过程:; k2 e2 j# }8 v- o1 U
    4 F! ?* k) b4 P8 u# G8 F) X1 b
    填充上行从左到右
    % b4 A, J) {# ^! W( [/ i填充右列从上到下
    ' r3 K9 ^7 f5 z! A5 a) B, P& m% {  H填充下行从右到左
    5 V. P2 \1 g# W填充左列从下到上
    4 D4 c) n/ y  ]3 _, u& _由外向内一圈一圈这么画下去。& z& v. O. c* \$ \+ ?
    3 z$ Y, {5 l- v2 q* O; T
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。; a/ M  H+ L! P4 \
    % `  }, e) Y& G2 s, B8 Z" P

    / a$ R" W' N* ?% b  _  z
    6 C# P! C0 G! O. x. m) y0 ?$ X7 X, L! h! k5 C3 \3 r; M
    $ p: I0 H- n' h& l% z
    class Solution {
    " d/ ]8 d, }  V5 A& Ypublic:" f& R% S. P- C5 a
        vector<vector<int>> generateMatrix(int n) {
    1 ^8 l0 }# Q4 K; |) t' P9 ]        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    0 @3 `1 J4 K( t+ L! u2 [% ^+ y, G        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    - s" g& m! i) E0 G, Q/ m: ?        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
      A% J7 @( p- c; R/ w' {$ S7 t        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    ! C' o6 @/ t1 f7 m        int count = 1; // 用来给矩阵中每一个空格赋值
    0 X; x2 ~9 T5 M) Q+ w        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位( j1 N" @8 H+ W+ S5 k& x  E! z+ u
            int i,j;
    ' W# i% s) n1 T; u9 s        while (loop --) {4 O7 J5 E- {/ p5 @7 D  u
                i = startx;
    ) w- b9 T8 U3 c1 d            j = starty;
    & _9 z: o9 F% Z) M* m9 F# }& S0 e: Z
    9 f& A' r. `4 I. J8 u6 f" E7 b5 l            // 下面开始的四个for就是模拟转了一圈
    $ h3 i4 Z: U0 v6 k5 v. t            // 模拟填充上行从左到右(左闭右开)
    7 ?; J% H) u$ @3 s" ~* W$ E            for (j = starty; j < n - offset; j++) {
    6 J! J! U: j8 G8 r1 P8 s1 }                res[startx][j] = count++;% }# C; E& ^8 F% L! D
                }
    8 z$ T* W2 g$ ~' c- `2 L0 L& r            // 模拟填充右列从上到下(左闭右开)
    ' v4 L7 G; k7 y* a            for (i = startx; i < n - offset; i++) {
    4 d4 a0 c2 I! s' t6 |                res[j] = count++;
    & u  R1 }2 J  e            }
    : |/ s* q3 F& P. n! @, Y9 S7 z            // 模拟填充下行从右到左(左闭右开)
    + ~* w* f* S3 P5 @: _. p; h2 ]            for (; j > starty; j--) {0 _8 N3 x3 K' F" ?* J( v0 t
                    res[j] = count++;
    8 @3 Q; E0 ~6 e! Z3 q  H            }
    - A  @- L  B* T! m$ }2 V            // 模拟填充左列从下到上(左闭右开), [9 y9 P( s7 k2 w- x8 ~
                for (; i > startx; i--) {" R- a2 U7 h4 n# ]' \- A
                    res[j] = count++;
    2 q6 M2 A  w1 m2 U            }
      A& H( j% T( l$ E2 D# J8 e) B! m+ a# z+ }
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)# W2 d4 I7 |6 r6 x
                startx++;, C# n+ g, }6 J
                starty++;, ^) Y( p- k# p  g3 I

    0 \. D+ n# ^$ C; }            // offset 控制每一圈里每一条边遍历的长度
    7 k$ w) }. ~4 ^. c) ]1 u            offset += 1;& o7 Q" u5 D/ s4 P; z1 G, r4 {& q4 M
            }5 r- h3 H1 F+ P

    3 s  K6 @" Z1 m( ]        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值3 |9 L8 i8 w- P0 b2 z" u% B
            if (n % 2) {
    + B* v. T1 e. C) r. o% Z            res[mid][mid] = count;
    / J- l0 J0 M% y; s9 c. T) h# \        }
    0 J' j2 l1 A% G; W' Y        return res;
    ( H4 u6 [) u" t( C    }' f; y" f: Z1 h. |" a
    };
    - N3 A; L! v% l( P; R2 z% S# P0 `; W) Z
    ————————————————
    " |: @! u3 }" c版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ; ~# A& V2 y9 I/ t* _" X( F原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450399 b* c4 i' ^8 l9 r4 @0 G
    * M, q) X4 S! k/ \& M
    - N" v6 B' C7 f; Q5 t$ \1 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-17 08:33 , Processed in 0.464740 second(s), 51 queries .

    回顶部