QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1991|回复: 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
    数据结构之数组练习
    " o: b& N  S5 R4 H5 o* ^1.leetcode704! `. _0 }+ e% t4 {
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    : E. M/ ]5 ?8 n# q( X; P/ D: `
      c2 s. S" i; |2 L/ F题解:升序 数组
    # v5 E2 ^, A8 v- R+ L' z4 m; I! k, M' z. u. W
    方法:   二分法0 N. o, R2 w' C# B2 K

    4 Y; u8 ~/ \6 Q- Z5 J思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    , `, B& u9 I: ^$ ^, v; M  j/ a2 S; g, o0 F) n. d5 c
    比较nums[mid]和target的值:
    * ]# K) P$ l9 y0 r+ g2 r+ \- H
    # F# A0 Q2 M6 \. E+ G如果nums=target,则下标i即为要寻找的下标;$ A7 @0 n7 D6 n1 v7 O3 n3 Z) I9 p

    1 _# W, i* i6 O6 j0 |如果nums[列]> target,则target 只可能在下标i的左侧;4 ^: [7 ]% c2 M) G3 ^
    $ B2 k/ y- p. W! E! D  J
    class Solution {$ L( g+ Q' S! ~5 y( Y# ?8 y4 ]
    public:
    2 s0 L, s5 ~' W) h' c    int search(vector<int>& nums, int target) {  q! q* I* n0 Q2 S# z3 }
            //区间[left rigth]+ K, _- Z& a+ h
            int left=0;3 [! W; t0 B2 _% s) Y
            int right=nums.size()-1;
    " l3 @" f  x3 V6 F0 ~2 L        //结束条件 left>rigth
    6 I* Y$ P: p2 q        while(left<=right)4 H8 m. z2 A: j3 I
            {( S7 x9 c8 i# g, j8 c% t# R3 `
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]6 D" d3 Z1 J/ |% P0 ~' D
                //[middle+1 right]
    $ m: @, D% I9 G) k            if(nums[middle]<target)
    + f. n( v/ o7 C: j4 \: D            {
    & S0 N/ V) L: K# S% j                left=middle+1;
    8 Y* d% `$ N* l4 o% r( X            }
    % \9 H9 k7 e  t  P5 H            //[left middle-1]
    : B: X8 A3 d* `! a8 H! S7 a- X            else if(nums[middle]>target)1 K8 k8 m- h3 ~+ H4 ?
                {) M( C* X4 _0 M7 ]6 d" ~
                    right=middle-1;
    ) h8 s: p, x, }            }
    $ K: W9 Y  E( L: j$ v: |  A& F            else{
    7 d4 J' ?0 C# A6 t+ @) R5 |" g                return middle;9 o; Z5 K5 a( T
                }
    - b0 F% m8 k4 f" b( E
    , }4 d  ]$ Y! |1 t        }: \% k5 Y5 C4 E& {! Q+ l
            return -1;; n) I6 u- F0 i5 \
    # _7 p" f/ y, r3 q8 t
        }' `! }- i# b% k2 J8 n7 H: O3 E( I% t
    };& n; G7 M, k7 L" [5 r7 W2 Z

    ) h, O* K- _' H0 P. o+ ]6 u注意:! n( ~, U- p6 e, K5 Q$ M3 w
    7 d; @+ R; c! H/ \& f
    (1)设立区间为[left, right],终止条件为left>rigth
    ; j) d. P7 z0 P, ~  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    # W( Q( E. a" Q; V+ P  (3)    通过改变区间的左右值;复杂度logn% V. x9 h6 Y7 B. H# [% R8 i

    & |4 n# Z) j7 G2.leetcode 27移除元素4 N8 |6 O' E- U
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。- Y8 F8 w, y. W

    7 r, i; r: F+ C- y8 _  w不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。6 }7 y# @0 \, a4 m/ a8 D  y, I

    ! `, u* I' t- Y5 A' q9 v- Y* W元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。, |9 d) [7 A3 ^: \$ K6 P5 S% \& y" T

    ( o4 j) y) B7 E  r% Y( \示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。/ @0 Z1 @/ A1 C5 l
    , V! E5 ~* U* }2 L
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。" W. G; a$ V5 l/ I' D. u

    ( _5 H* w  b  f6 c5 k思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    9 P  J( v* Y( J: b" P$ G0 c: i" s$ \$ ~
    方法:双指针3 l0 I6 ]0 R$ J0 H, x& O
    6 z) h. r- h6 _1 K+ l' u" B
    class Solution {2 o1 |% j) a/ M
    public:
    / a7 Z0 Y: |) W5 v+ F% W+ r8 h    int removeElement(vector<int>& nums, int val) {
    8 F& n2 ?7 D/ p           int solwIndex=0;
    & y; \( X* p1 R0 B& B% J           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    5 e) Q( T; h7 s           {. y2 P8 d  g# Q8 q3 G3 V! b4 z9 Y
                   if(nums[fastIndex]!=val)$ B- \+ L8 r. v$ f) [
                   {
    ; D' w7 g' ]# w9 T& l- g                   nums[solwIndex++]=nums[fastIndex];
    . x) `. i& \$ W( Y, y               }
    ; S& x8 f1 h3 x* S8 o% a           }
    0 p0 m) D/ H* b  I1 }3 ]           return solwIndex;
      A5 C* i" }+ Q; Q. {9 ]8 H0 v    }8 S9 p! J7 k0 j3 `$ ?* l1 V5 Q+ U
    };' S4 D" P( p+ E3 T
    solwindex:用来覆盖
    & P. k  D1 d! W# j0 ]/ \, ?; K* o0 u! D* V( B8 I9 K, G' D
    fastindex:来找删除元素++; ^* a! W+ ~$ G" K- m
    : X" B8 f2 `+ q7 x( k
    3.有序数组的平方4 d; y0 z+ c! q7 b
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    2 b4 r$ Z; l: v- u, m" f9 [' S( [$ S% z; v; Z
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。2 \1 e- X) c3 o3 W# f$ u* p( k: F

    + B/ r' r5 ^& T# d& `) g那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。: w: A( V7 I$ P1 i; ?' t: y1 L

    0 j' T- x  n9 |( k) d% B) D此时可以考虑双指针法了,/ w+ c* |+ ]& g5 B/ e! Q

    / y. n0 f2 o1 x) N% g) f: z9 vi指向起始位置(负数),j指向终止位置(正数)。) _# @2 ^( x4 H1 G
    6 O% @6 C8 ?5 y6 D
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    5 H, k* c- k( `$ Q. V. a' s6 P8 v: l+ M( M: x( {% X
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。* ^% k( @$ i) t  E& D
    8 f' M4 N* U; f$ S! U* {) z
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    / S6 @% d0 l6 t% \6 D6 p
    2 E' Z" f2 |/ R, D. u' F+ t) H  e  fclass Solution {" p8 u3 c8 S; Q: ^& z2 c! Z: t
    public:
    ! t) l" ?7 g0 o    vector<int> sortedSquares(vector<int>& A) {
    . m6 d$ s8 ~6 [        int k=A.size()-1;
    , k- y" H3 J' Y        vector<int> result(A.size(),0);& S/ R* ], [* x
            for(int i=0,j=A.size()-1;i<=j;)* f6 Q2 v( [! E" W3 _" _/ n
            {; p9 b1 N- K% w- v4 C& k, X
                //遍历一遍
    2 A; V9 q. Y& U/ |1 X            if(A*A<A[j]*A[j])
    ! c. o. x) O4 F! `. l5 f' u            {
    & X1 G! ^7 V: H2 q% l/ G$ f- W5 _                result[k--]=A[j]*A[j];+ G7 Y* y. E6 H
                    j--;8 S% V$ `+ L2 c6 s1 Z
                }
    . n0 f. b: t( W  E2 \# s, {8 n. j            else
    4 X" Z, G. m2 O/ [            {, M# f# E* x" \: v% p: e
                    result[k--]=A*A;( L( e/ _# X# \+ ~" Y
                    i++;( T  z! \- F: P
                }
    9 `. f3 ?) y* ?; L        }
    6 n! L) D% M& z        return result;! H) N% g) f7 `4 b9 _) B5 x
    + B' I7 z& y  q5 i7 `9 z" k
        }2 l1 i5 l& [0 H
    };) p; ~$ p. p* e$ ^

    : h8 u$ g* S; A" s% e: a, k4.长度最小的子数组
    $ K2 l% @- [. d. {) \) |! \$ y/ a* Z给定一个含有 n 个正整数的数组和一个正整数 target 。
    : W/ k1 Y: H6 F4 G* z) n
    7 U* L" Z# L7 ?) C5 p找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    - S/ F9 Y$ b. U: u" P; m1 S5 I; Q" D+ v9 H: @; b. k* A
    方法:滑动窗口法5 a% R2 U3 s9 v% |6 x& F
    " _% J# n3 N" n! I& _  s5 o* c) @0 m5 M
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
      ~) {+ r3 I  f+ e  v$ m) @) t2 Y8 r- m# c+ r) M( W  E
    三点重要:3 z4 i# ]4 c  o1 I* E' I
    $ q( }; D3 u4 R. a. E) n0 j
    窗口内是什么?
    , l' ]4 g4 [8 Q9 e+ Q2 V窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    6 F0 u  b6 f0 p  n! }如何移动窗口的起始位置?
    3 s, ^" h* k  v( _! h: ]窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了, ]" \/ z3 c5 o7 ]5 T, o
    如何移动窗口的结束位置?
    " d! ~3 l! L- A* M9 b+ y- c窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。5 G( r2 \: G- N9 }2 v7 g4 X
    % y9 l" g- w- M) k% M0 u
    代码如下5 ]; P, _6 H% k* M
    / W6 d! B( [* T& v: d# M
    class Solution {% |# _# w% o/ i( C3 g
    public:9 v8 Z! Y$ @6 t/ n
        int minSubArrayLen(int s, vector<int>& nums) {
    % l+ T1 E( D+ b7 i        int result = INT32_MAX;
      Z9 r& |6 W1 l* z/ c: I3 {) d6 L        int sum = 0; // 滑动窗口数值之和  j5 p6 d* p3 d
            int i = 0; // 滑动窗口起始位置
    3 w, T8 i9 l4 J' r  H8 e        int subLength = 0; // 滑动窗口的长度1 m2 P; _- A( q( J* k
            for (int j = 0; j < nums.size(); j++) {
    ; H' j  H7 d8 N; R            sum += nums[j];
    + N2 o" Q$ o( m- H" L            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    . F' h& t& v; o            while (sum >= s) {, e% f9 F8 N0 d  H! Z" [) t, E
                    subLength = (j - i + 1); // 取子序列的长度. @0 X  ~* b8 ?' }/ W7 @- E( V2 v
                    result = result < subLength ? result : subLength;//一定会赋值* {. C: |9 Y) v
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    5 j( k6 K+ J3 ]& s2 v; P; ?            }
    6 X/ Q  z+ `# U" [0 v$ o1 b        }1 Y" W% v9 q  t8 @" x* p# j9 Z
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    . a- C  T8 Y2 w        return result == INT32_MAX ? 0 : result;
    ! s% ]  q" v' @* Y/ \    }) \& I! ]7 N- `3 @
    };, ]. e, e# a1 ?2 U, {
    3 p# |5 R8 R4 c  `) d. b
    一旦大于,就减去左区间的值1 u* h, M6 g0 H6 W2 q

    0 y+ A9 r  U) w5 e9 j% ^5.最难题螺旋矩阵||/ D; d, N' k6 v
    模拟顺时针画矩阵的过程:+ q+ H% Q: _1 H+ k" S) V
    - B+ s/ d4 [3 S, }
    填充上行从左到右
    & \0 `' U8 M, `* g填充右列从上到下
    + I8 {2 Y/ \! j7 v# }填充下行从右到左( y/ d' W% c% ~
    填充左列从下到上8 ^7 a- ^$ \4 R& R
    由外向内一圈一圈这么画下去。
    # {9 Q- m  |  r' d6 B; n! }* j: i8 w; ^1 J2 S2 u+ M6 ~
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。/ m% n, k& `) M( T) ?

    - Y3 z2 K; X6 E! |! X# j/ H2 T8 P/ F7 }1 \4 c
    . R) K* W% P3 Q$ w1 f8 E9 b

    - ^3 Y. ]$ k; C4 n7 ?9 n% a
    0 W8 t! }# @2 V% ]class Solution {! a% k7 e$ f: ^; f
    public:7 A- i$ _* w* D' l2 w2 y' p6 y; y
        vector<vector<int>> generateMatrix(int n) {
    . r' E4 T4 M# U- ^3 t        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组: a- P9 C6 Z, q" H8 H& G
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    5 s* P9 O% K! ?3 m        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    . |; P0 K( @& R  p# Q* O, b. Z        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)8 C7 o, q. Q3 {% w1 p" t& L
            int count = 1; // 用来给矩阵中每一个空格赋值
    ) |8 J) i3 x! }/ v2 E" A- G        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位9 ]* m0 f2 E4 k8 u0 |- T, Q7 q  V
            int i,j;8 ^( }4 v+ G# ?8 F/ t& I
            while (loop --) {
    ' ^3 s+ k; Z% U* i% q9 w  n; ]& ~            i = startx;2 E& k* X3 q4 R4 k/ {
                j = starty;6 M- K' v) ^; f$ ?" X: {

    2 u- x, K2 U# A/ }% s* w0 Y            // 下面开始的四个for就是模拟转了一圈' V# F! D% v/ ]
                // 模拟填充上行从左到右(左闭右开)
    3 H, M8 a" q: H( @! p* W            for (j = starty; j < n - offset; j++) {
    : a6 r7 O  p0 E8 a                res[startx][j] = count++;6 q+ J/ y- p2 |5 @
                }/ u, `9 E, o4 Z" F& ]% V0 S
                // 模拟填充右列从上到下(左闭右开). e" |0 }  q. c' N5 M1 a9 U
                for (i = startx; i < n - offset; i++) {/ S+ u) ~5 s  l4 F0 g8 o: M  z( |
                    res[j] = count++;
      k6 _9 X2 c! g" R. O( l, b7 |            }9 w* p( E5 S% M5 O- b3 |
                // 模拟填充下行从右到左(左闭右开), c* c0 ^1 M& |
                for (; j > starty; j--) {
    * t5 O$ I0 C3 h1 j, k& P. N- t1 l                res[j] = count++;
    & @9 B+ h) ~( G& p* X* ^            }! P* b# S# \" S# O6 @
                // 模拟填充左列从下到上(左闭右开)8 }) i. Q( u! [$ p1 H1 L; Z
                for (; i > startx; i--) {
    $ P2 ~" E7 H( z; f                res[j] = count++;
    7 Z5 K- _+ {1 c            }
    : v3 E) x0 Y, ~" H9 o* k0 D5 B7 q, }% A9 Q
    6 q3 k  m+ X9 I$ a7 Q$ Y. \            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)2 t$ `# \) y* o4 D2 G
                startx++;
    ; @* q1 P9 n  {, H4 E            starty++;# y* C( a1 w3 U- `
    + T+ w, ]6 T( P1 R$ ]5 j8 C0 [9 G
                // offset 控制每一圈里每一条边遍历的长度' P& q6 t) y- S' k- b
                offset += 1;
    5 A7 O/ m+ ?# h7 g. \        }3 ~' d/ D& v- b8 T/ v; b

    9 d( B, p# [" ?1 ]        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值* n, @- Y8 W' C+ V& x+ V. u& }1 m
            if (n % 2) {$ m' p3 n2 U, j7 N6 l* Y
                res[mid][mid] = count;9 d9 L  _0 v! X/ f, }
            }- u9 F1 I" c7 j  {; D' y4 K
            return res;
    % h8 o, c& |; s, O/ B% E2 W    }
    + W& s6 }! H. i# v3 x+ v};
    * q6 E7 X+ k8 h1 r: `) e; I( i4 ~: }1 G
    ————————————————2 B) S6 C, s, D3 K; E5 e( _2 c1 S
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    * C/ |6 p8 q# }1 Z/ [9 ~原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039. ]0 }# U) |! j9 ^" v

    3 q+ Z/ M( L7 n1 _6 @: `; A- H1 D2 x* Z) m8 i
    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-12 14:52 , Processed in 0.428434 second(s), 51 queries .

    回顶部