QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2065|回复: 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
    数据结构之数组练习
    . y% r' Y  Q/ S9 N/ n3 Q* _8 x" |1.leetcode7040 c" ?* g' ]9 d/ ^6 Y# Z% i, ?# {
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。. w) f, `% k- M

    . F7 ^5 u3 S1 T- j) y2 {6 V0 G题解:升序 数组! o) I9 Z. ~& a- `) ?/ n. y/ ?8 A
    ; p8 o) C) Q5 B
    方法:   二分法
    + V7 q3 Q& t' |4 B' I9 @- ]! C8 X( D2 Q7 \, H+ g% r. U; J9 h
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    * y; l, q! ^" e! o" e' R5 X; w0 q0 H. \
    比较nums[mid]和target的值:( }8 `8 B1 {3 p! ~( r! b
    & g- Y5 a) f( E
    如果nums=target,则下标i即为要寻找的下标;
    7 `- j" @: I( a; V/ @3 I1 k0 l
    % d' a% \# T3 |- |; a' w如果nums[列]> target,则target 只可能在下标i的左侧;. |$ o* X7 V1 ^& h
    ' n# z! i, \- K* `0 I3 D+ n; e4 g# L
    class Solution {8 y, L3 w8 y0 a  F) m
    public:
    & U% K! N0 d: T* L3 V6 U    int search(vector<int>& nums, int target) {9 G$ S+ D8 N" c/ ~
            //区间[left rigth]; X0 I  {' i3 m8 a8 C. Z% J3 r# j
            int left=0;
    " U$ M/ o- R9 K1 T/ Y        int right=nums.size()-1;
    5 F; W8 f) B5 K; J3 L2 O        //结束条件 left>rigth! @" Y9 o- a' U1 U  Q# h
            while(left<=right)
    5 @$ `4 m) R! F        {1 X* h* j0 Z5 a8 p$ b
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]. ?) W" b, q8 Y: n$ W/ f
                //[middle+1 right]$ p! Z# y' b5 |& I
                if(nums[middle]<target)8 o" I% i. N9 W7 |
                {
    / t4 ~2 R( p3 c  j  h7 q) ]                left=middle+1;  x, I6 P- F2 n: {+ ~7 A. B. m
                }% G1 D6 _- V0 ?9 C
                //[left middle-1]! a5 s5 W  X4 X! _! D
                else if(nums[middle]>target)
    ! Q$ s( \" z: U% c! d- W            {+ I* T/ D/ t# |' A: A9 b
                    right=middle-1;
    9 q0 {  R% r% S1 n; _            }. H, g1 h9 y6 l
                else{
    0 A8 l1 ^; G! s2 u" i                return middle;# ~/ _) Y' Z  ^1 P$ T9 T% k
                }; ]0 N; b: U5 t1 u
    ( _1 X% x! k9 |- c
            }
    3 ?8 I; {5 |& A! L. Q3 V        return -1;* G7 g# v) Q7 y/ c5 Q

    " q% R$ r0 |+ V; s/ `7 }3 Q( w6 ?    }( v6 v) Y+ Z- j1 Y; t; o  `3 [8 @
    };! v7 ]7 _- @$ G

    $ f6 C- w7 t5 a) B* |注意:
    - U3 D$ @. K4 @! V: Y1 E
    % o8 B7 I. e- k8 ~7 g1 r! t" @(1)设立区间为[left, right],终止条件为left>rigth: L+ b  r: w# ?/ ?6 K$ h9 w
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    2 k! N" F6 q2 `. @9 u* i* y# `# q2 W  (3)    通过改变区间的左右值;复杂度logn
    ' _, s7 z7 R( a: f% k  r, I' J/ q8 [* ~* N0 {  K9 O$ A7 T9 S
    2.leetcode 27移除元素
      s; \  w8 T7 `8 [; j给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。7 e6 W& |* n. Z2 {% g. ]
    ( R  a1 v% F+ `, ?1 G# F( R
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    2 c& w9 }, b1 ]* P2 o2 |9 l: n, S0 G6 a9 M: r6 }+ y4 r
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。4 a! t: b3 C. j6 J7 `; b; o  S% k

    5 C1 U  `) `( h+ a# S# T示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    " N1 Z5 ^0 J" h/ B8 B* h
    + C7 R: P/ f: M+ g/ S9 l  |示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。$ t2 y: V3 e/ [9 k; C5 {

    0 ~; q! H. _6 V( x思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。. L5 D. p4 X$ R. S- [9 ]9 i
    + A% Z/ m, N4 o- x0 j- t5 |  b" z
    方法:双指针
    : I3 o3 K# l7 D9 z  d% q7 k6 g! M5 M! F2 }5 o' l3 e. S4 A2 s
    class Solution {
    8 x# F* `; d  r/ o+ x/ C# E7 p$ Lpublic:
    " y% ]% r3 U( o    int removeElement(vector<int>& nums, int val) {0 ^: r% }' \# v; f, V0 b/ ~$ W
               int solwIndex=0;/ Q! r4 U/ G- n0 S3 X
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)8 V4 N* ~. J) o$ E! P
               {, H0 V% ?7 p5 g! p' v
                   if(nums[fastIndex]!=val)6 u* _8 X5 W! h, y
                   {( K& f( e; D& F! S' |: Q5 }- U
                       nums[solwIndex++]=nums[fastIndex];- z& f! P9 b, l; v- l
                   }
    " q6 x$ x, V! z7 `3 M           }, X* `" ~5 Q8 F' C0 L2 q  J5 w( g
               return solwIndex;
    4 z2 e7 @' b4 ?3 M( |  v  Z( _% t    }. Q' P, Z/ j7 b# m% P
    };
    6 H( F9 C. Y5 {* ^' ssolwindex:用来覆盖0 ?+ Y( g0 n8 i: G! k- t4 c( v
      O, \( |/ b! T: H3 R! x
    fastindex:来找删除元素++9 z( a3 _* J2 y7 b; S+ N

    8 }! i: M5 b- i; |0 z3.有序数组的平方
    # e7 s; b2 H- _$ M6 v给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    & C4 \( `" e7 @7 H7 ^7 I' A. d+ ~1 [8 [- @6 F, _5 y  K! J
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。: _" d, \  Y; F8 o# n+ l. ~2 y

    ! a2 k& W* i  X  ^那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。1 [0 D) o  m( c2 T1 u8 \$ v; b
    ) E6 m3 O0 U% U2 J$ {/ P# c
    此时可以考虑双指针法了,2 K. j. h# M& j- u  C9 K& r  ~9 P

    . p  o& L7 [# G5 k( }2 M  ?' O) Z, Gi指向起始位置(负数),j指向终止位置(正数)。6 A% \- `+ H4 d% }; ^; B0 a  y+ x
    # d; z5 J, H( p7 C( ?9 I1 y' @: N
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    ( b! {3 F# [! u8 j9 U/ s) ~8 O, E9 ?' v/ I$ A; u9 l
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    3 g; k8 x! o( X0 e  X6 z" i$ A4 M* y' ~  ?  W
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    ; ^7 \. w5 W4 Q2 `- n5 S6 ], s  r  S5 K9 @) f, ~2 r
    class Solution {" \- B" g8 z1 Y/ U8 U# k" g* t
    public:
    5 W( {6 `  ~, M! E! c    vector<int> sortedSquares(vector<int>& A) {
    ; T! B2 B1 @$ `, j( ], w" V% T2 E, l        int k=A.size()-1;- K/ i/ X; k# q% a! a6 ^, w
            vector<int> result(A.size(),0);$ N9 p3 [( U5 z: c; Z2 g
            for(int i=0,j=A.size()-1;i<=j;)  R  r4 B8 O9 X& T8 J
            {! g. `9 A1 f6 Z: U
                //遍历一遍
    ' m. H5 V$ n- r  ?; _  h0 @$ B8 t            if(A*A<A[j]*A[j])
    # b9 ]/ Z, |3 h* q' l$ u; \            {
    6 p; ^+ W- X  H0 F: M                result[k--]=A[j]*A[j];* U, |: ?3 b! [6 ~- X- K: P, a5 D
                    j--;
    ) Y8 J; J" x5 `) b) a# ?            }
      l: @  v9 R& M: ^9 P$ G            else4 v# w' F/ m/ T9 Y8 ]
                {4 N) Q4 B, r$ Y3 h
                    result[k--]=A*A;, w, ?* f5 u; L$ g& L
                    i++;3 |8 r7 |" |3 N/ E( [9 K
                }* S  A9 {! N% g/ }/ p% u
            }
    6 {7 i9 C7 ^# I        return result;
    " L  i: d8 D$ e4 N( v% [
    ( W8 K8 D; S9 w! ]8 k    }
    6 d. |. q9 X5 o1 z};
    ! r) u" ^& Z9 [5 E3 [6 D' n  G5 t" m5 Y6 b; p
    4.长度最小的子数组8 }7 ?, H# r  \( q+ |+ b9 h, A
    给定一个含有 n 个正整数的数组和一个正整数 target 。
    ! x' N/ F9 Z' `1 ]+ @0 Z2 l$ d' E# ?6 m% d7 i
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    * j1 n+ F1 |9 ^4 a+ e% I7 l6 ?2 R. f+ h/ _& c) o5 Z, `) g0 \
    方法:滑动窗口法7 _1 w" X/ a+ s( T. v; ^- T3 H

    8 w; m- f2 F" B. O/ D- g就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。. K* J  D# o6 N  c" ?3 i3 b
    ) G% N! O* @+ `
    三点重要:
    5 Z; U, Y- c" m) ~( u4 j' ?9 Y8 D5 s" c- {
    窗口内是什么?3 N$ s. M: a- ?
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    8 m; j4 y8 ~7 }# l& B% j如何移动窗口的起始位置?
    " y" p* y( Y: t; O5 v# m3 N. Q窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    $ M; w) a& k& ]1 S' ?: b+ o如何移动窗口的结束位置?- t) Z8 [) l7 J+ S
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    " p  j5 d( R! |4 f' V* ]7 D, n% K3 k* `$ v& b9 ~# o8 |5 K
    代码如下
    / N5 q# T# R6 g+ ]
    & J- f. ?; r8 L2 S- C0 Cclass Solution {
    0 R0 u1 T4 f6 \- t/ S9 Opublic:
    " T: [3 {& O3 e    int minSubArrayLen(int s, vector<int>& nums) {. {) T+ ^2 P$ d. I5 @# J! r
            int result = INT32_MAX;# n4 |" ?* H# Q+ k) K5 y
            int sum = 0; // 滑动窗口数值之和
    - m9 |4 Y9 q2 b) k- {  e$ Q        int i = 0; // 滑动窗口起始位置* Q/ j$ F8 V! V! S  @5 q: `4 \
            int subLength = 0; // 滑动窗口的长度1 `! |& C7 x- Z6 ], d
            for (int j = 0; j < nums.size(); j++) {& l+ E" F* k1 M, ^1 ^( z
                sum += nums[j];/ Q$ E. A" r% `4 K% y& s' C# y
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    # T( I4 r* t3 V( Z            while (sum >= s) {
    ; d/ x5 d) f8 T  t! n" A$ D7 w                subLength = (j - i + 1); // 取子序列的长度# j! Z  b3 k# |) V
                    result = result < subLength ? result : subLength;//一定会赋值
    " l. R3 a- V0 C7 ?                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    6 C& b& Q  V- a# f            }
    - F" z3 U% I* m* X0 ^4 z3 S        }
    4 f( ?2 `1 N$ L7 F0 B        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    6 s1 e3 `8 e) t: Y7 x7 s+ I+ C        return result == INT32_MAX ? 0 : result;
    # n5 A, j. s5 a9 Q! W" `" E    }
    ' e. y: B& S  p' E. f6 ^, y};  ?" L7 w! s2 s, ~4 E

    & F" h0 A5 Z5 G( w, L3 \2 p" X% [一旦大于,就减去左区间的值1 F# f8 |& e: N! k' a
    5 b; Z3 I/ o8 T" V
    5.最难题螺旋矩阵||
    # K3 _" I5 L" p" f6 b模拟顺时针画矩阵的过程:
    9 m* A# B) z" h7 b- }3 _1 p) h: B  ~2 v1 O6 K! l5 U
    填充上行从左到右
    $ F& T) Y+ s8 ]6 Q" }填充右列从上到下
    + O( S' r; v0 [9 u6 h" v填充下行从右到左7 G4 z$ y0 C5 n9 r% a) \6 l
    填充左列从下到上
    + X# q$ Q7 k0 j  l( q1 F由外向内一圈一圈这么画下去。2 ~# c9 O, {, V1 j0 q
    $ N/ S/ A" ~$ A
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    9 n: _* x/ K& D- L5 n2 j+ X, S$ c2 q. }

    6 `3 w" V- f, |, K+ D; w
    * t1 D0 k$ H6 Q$ C5 y! Z# s) X' q( {2 n. y* y" E$ e

    . ~+ E& }$ |% J) b5 p" bclass Solution {
    * E; l. u* H7 e3 T$ s9 z0 t$ A1 jpublic:( G6 R! R2 P( Q" u( p) w5 A' D
        vector<vector<int>> generateMatrix(int n) {
    9 R( e. o; H3 b0 @: I3 `1 r8 A        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    3 H4 ^1 s9 N3 g$ m* v        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    % l& I8 {0 d0 ~1 m        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    # o! J1 M4 |$ K, _0 @5 J" }        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)7 |+ ^  {0 F, x8 q5 f6 k, C0 U
            int count = 1; // 用来给矩阵中每一个空格赋值' d3 N8 l' D1 a1 m4 V3 D! |
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位% c& z& ~5 E) D! _& }+ c, h
            int i,j;
    # b8 W: G) C+ q& k        while (loop --) {7 C  b9 y! p$ ?; N& r5 j
                i = startx;
    * m# f0 B& U. ]$ m            j = starty;" V: x% D+ t5 f% Q( y

    % j: P; r5 Z# x- R: V+ W; |  D7 Z2 H            // 下面开始的四个for就是模拟转了一圈
    * z3 F. m" T0 f$ k. Q4 N" L: p            // 模拟填充上行从左到右(左闭右开)$ x  f3 c* V' }( x' x( g
                for (j = starty; j < n - offset; j++) {
    / `# t! f* {; k. r8 g8 m: r( O                res[startx][j] = count++;5 l* W1 G9 |: }3 D' ?  N
                }7 m; C1 J: e5 v0 t3 I: q
                // 模拟填充右列从上到下(左闭右开)* w: t" `/ G9 H9 ]9 ]' A: D4 M
                for (i = startx; i < n - offset; i++) {8 [( m& R  \- `
                    res[j] = count++;4 r* l7 ?/ R3 e* c$ ~
                }
    " W% [, l( i7 C* D            // 模拟填充下行从右到左(左闭右开)
    ! `7 k. s$ g/ D5 t/ d            for (; j > starty; j--) {* N8 ?. }# n+ k4 ?2 s
                    res[j] = count++;
    ! h6 k% Y9 K0 w+ q3 w( j) Q            }, P$ b( ]8 f: I  \; U% ^$ z
                // 模拟填充左列从下到上(左闭右开)
    ( y8 A* }- ~) e' P            for (; i > startx; i--) {
    9 Y3 M: r" v, M. y                res[j] = count++;% R/ E2 h! r- }- _9 K: {
                }0 w9 H, b. a# B- O

    - n, \- f9 w* n4 S) \6 f  y            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    : r# W9 O* ~& F7 f. r& H            startx++;5 G5 w. A% e4 R# N* m3 ~
                starty++;" l% i2 P$ o" P' _* K) q

    0 M( z3 J/ ?* V% s4 l            // offset 控制每一圈里每一条边遍历的长度% E" p/ l3 l& w; ~
                offset += 1;* Z0 Y# g9 d; {* Q1 ~. H  i
            }
    ! n1 R" O. n( @% Q/ W
    # c) F" w3 L! j" T6 X( J$ z2 j& d        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值9 A* J# G$ X9 ~) U- L& P
            if (n % 2) {( u+ s9 a) L3 k! |2 r9 p1 G
                res[mid][mid] = count;' Y8 Z( C7 `; I2 ~; o& H+ H
            }
    5 W: j' ~2 j9 f' R8 n. {( Z        return res;- c* W" d& l' U0 G$ I
        }
    * T7 _; K# @. E: x, \: T9 ~};
    # z3 f$ r/ f& n& L) k' p
    . `' U( H& f& _  C————————————————
    ! ]& _9 \) Z$ r9 N版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    1 Y0 [) o" G/ A& f3 D4 W8 s原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039# N2 P! K) M0 P' y

    0 {' Y- b0 S( k. L! ?: B* B
    ( r/ p$ o$ x, a! _
    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-9-13 16:31 , Processed in 0.406848 second(s), 51 queries .

    回顶部