QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2025|回复: 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
    数据结构之数组练习
    # p8 |) D# U& I' U* o4 U9 R8 D+ h1.leetcode704
    " ]8 E0 e- m- c: f( j+ q给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    6 Y" l+ j8 Y, T# N( P5 W$ V# ]8 M3 z
    题解:升序 数组
    3 c" K* B0 W  y7 d; _8 p. }5 @: y/ i9 `( M
    方法:   二分法/ C; K" }: ?- Z$ s
    / t1 Q' g1 S9 N- y
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    & c- w6 W: h0 |' A  ~% U/ T$ t* b4 E3 Q1 E$ q; s8 _' W5 B/ {
    比较nums[mid]和target的值:8 ^# r# W: d0 f0 _2 o& _
    4 @* _6 d4 h; f3 r/ k
    如果nums=target,则下标i即为要寻找的下标;
    : n* S! J$ H2 D  K8 t* U3 L- z) [
    8 e  {0 r: a4 `0 u6 g如果nums[列]> target,则target 只可能在下标i的左侧;
    . I6 p4 A+ d1 Q" T5 o/ Y
    ) y; t9 [) e+ h3 e8 c1 I2 }. vclass Solution {
    : N3 X! ~1 _/ Wpublic:! D* R. H5 H6 g' U& z
        int search(vector<int>& nums, int target) {/ I, \& w$ l- g- Y+ D3 V, `
            //区间[left rigth]
    : p2 @. L& p, s. r2 p6 F        int left=0;
    1 @2 C  H( V9 B; t/ K        int right=nums.size()-1;& s- u9 e7 k. t& F3 M; u
            //结束条件 left>rigth
    ( u! Y  t) W) R; D" ~$ s        while(left<=right)
    ; M, `. G' ~8 k, }/ u! t$ Y        {
    - y; J7 \# v! u3 i7 x            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]2 O) r' H% v% q' L( s
                //[middle+1 right]
    5 z0 c/ j) U5 y            if(nums[middle]<target)& E8 I! C& b+ R6 G6 N6 e* c" k
                {) w. i# Z" s% Y9 y6 ^2 ~" Q6 E
                    left=middle+1;
    4 ~* i+ r5 Q- c- _" k2 \8 G! J  q: r            }  N& ^6 z8 m& }0 m/ i& q
                //[left middle-1]# j+ |% Z9 x! a8 h" K
                else if(nums[middle]>target)" l" j' k; B' n0 \
                {. X% S: p& p% R! y' A
                    right=middle-1;
    * s2 L+ h* L( m8 S3 ]0 w            }
    , j7 n6 [8 I% J# V' z7 ~4 r            else{
    9 I4 g' ?' c3 r                return middle;
    $ q$ f. M2 c6 Y/ T, q) v  ~: G            }) P1 S6 Q9 n1 O- p' ]
    " {+ ?5 c* F& p, [! s: I
            }
    ; U# ?  x+ Q' t$ N; n$ ?        return -1;
    3 H1 _" {% z* ?) c7 w9 ]: g" P( v$ T2 S* v" d( u% M$ e; @
        }
    6 h3 ^; a& z, N};
    0 m# X. T' D# k. \2 z$ x8 p/ e! L1 y* t4 F+ M! y* G% \
    注意:
    + a2 F* V. n  j. w. D/ f
    ; p% w0 L1 j! B, i% v0 M(1)设立区间为[left, right],终止条件为left>rigth
    ' e4 \/ q; u+ S( x  (2)   (left + right)/2==int middle = left + ((right - left) / 2)7 N% }0 o: f, z' l( l
      (3)    通过改变区间的左右值;复杂度logn
      s& q( _& r- h
    6 l: h; ?3 d4 |/ x* M5 ^/ `2.leetcode 27移除元素
    - Y& K9 [% j$ w4 L) z  U& X给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    ! X% P! ]! u4 I$ ]; R* u% Z% _0 s( A
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    " e* S8 `7 U, S' j1 f2 d8 V' x) c: }* t/ x) r: h" _
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。3 m! n+ }: I$ I6 j! Y9 y- P5 h

    / N! z2 ^) ]# O3 k+ N: q0 D9 c2 R示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    1 X/ W0 l$ `: M5 g- [( [' d* P3 k! u9 U; C5 \+ ]+ }$ C
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。1 R7 y& }3 ]' s/ w% C2 e; I& N
    4 ]' b! J- y1 @# u. X7 L
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    2 g6 l; ^' \2 Z" D; p1 c' g1 W+ \; W
    方法:双指针
    % O# W1 l" n* C7 d" C% |$ J- A' ^: a2 z& s0 P
    class Solution {
    6 E0 H7 u4 w8 W6 {7 ppublic:$ M' N: d% c' ~
        int removeElement(vector<int>& nums, int val) {' P; W3 p; ?" ^. t6 H8 ]8 t0 |
               int solwIndex=0;# N9 u: ~& B! X' o
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)9 i- I/ Z" u2 s/ F: W4 m
               {2 Y* S/ U5 B3 S
                   if(nums[fastIndex]!=val)
    , n9 Z, e5 Q: S9 q, j5 s               {# {; n( \) S; I  r: n* {! [
                       nums[solwIndex++]=nums[fastIndex];5 l# i' G: _' L8 R- g$ f
                   }% L+ F8 }3 Q" P& G. Y
               }. ?; V9 K( ]# E
               return solwIndex;
      M: b) ?- N8 r! a- ^    }
    9 R+ w, R7 H2 _! q/ c; U};  [1 L* K3 y3 q, N1 c, W7 T
    solwindex:用来覆盖
    3 }+ i  t- Q# u: \0 n6 ?
    - D1 O% N' n* L; {3 ofastindex:来找删除元素++
    4 D  {5 j1 G9 f
    3 B1 g! E1 ^1 K& l9 L3.有序数组的平方( W0 s! ?9 v+ v% K0 s
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    4 c% ?/ S" o) x$ P) t& z' p
    9 H& I/ }9 h, @' g9 H0 ?+ u数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    ) t! v5 a1 l' [! R! u6 O. ^6 Z, R5 Z7 m  k# ]1 m: T
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    ( b; k5 ?2 K% k0 _# m( ?5 S- e! t8 O' X; b2 S- R7 b: s5 p  s
    此时可以考虑双指针法了,3 x7 |+ V. e  U6 r8 `

      T( u+ h$ @( ]+ _8 Pi指向起始位置(负数),j指向终止位置(正数)。
    1 c' z8 Q+ n" T
    8 G2 |; x$ h+ \$ u1 S6 r6 r定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。/ ]6 ]8 w0 o8 \# y' F
    0 S  `" g* Q4 h- f5 c: D
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    4 U! S' q9 y( Q( S8 C6 F, F$ k0 {( `5 n! ]1 `- {. G7 I
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    1 {3 z5 K. w6 K* T" s
    4 D% a! k# {* W, Jclass Solution {
    : D! x9 |; t7 o9 l5 ~public:
    ( D3 |, w2 y# c    vector<int> sortedSquares(vector<int>& A) {6 J4 O- _. N- w4 k. b4 M( y( c$ ~
            int k=A.size()-1;- ^* G$ w1 y; n% g3 m; ~
            vector<int> result(A.size(),0);, m1 N/ G7 S; Y+ r8 s+ K
            for(int i=0,j=A.size()-1;i<=j;)1 l4 [! @6 ~- Q9 E4 S
            {/ g4 P, j- L# O1 x, l& s
                //遍历一遍
    8 x: l! r: C: V; A5 D6 f            if(A*A<A[j]*A[j])
    $ q# M& H7 ~) L# J; t& T            {
    ' a( Z4 m0 P9 P( Q8 W7 U                result[k--]=A[j]*A[j];3 q$ i5 R/ M3 K+ X, c& F2 X
                    j--;, E, T2 {9 D5 Z" `# l
                }$ P" g5 c2 v. V/ j
                else
    : \2 J. u! K$ z- \. ]1 [" v            {
    + m' M/ D* U8 m: s                result[k--]=A*A;7 v. G2 L/ j+ w' F
                    i++;  E* k1 V' g/ _$ q' z& X- D  _: _
                }
    9 x$ d7 m- Z/ G7 D, d1 c# ]. n        }4 x+ H3 l+ {0 w* q
            return result;
    " c# k9 W3 }# R& i2 e0 T0 h( q. P7 E: U
        }) f- Y' Q6 E3 r; |
    };
    , x& [; \# |) z% Z: e6 `* b, H' _4 K" O7 e( c9 [  b: T0 J6 ]
    4.长度最小的子数组
    ) p) x) U1 d+ o7 Y, d1 ?- |2 }给定一个含有 n 个正整数的数组和一个正整数 target 。
    - u' w) [' U: p3 N2 F3 @2 `
    # e& V0 G- h) l! b7 P找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。* y7 x+ U$ W: l: |# P( }+ \
    , J+ m/ U, \5 b4 Q
    方法:滑动窗口法
    & l$ [, {$ @& O3 b2 U# U( E3 a3 X- ~( G
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。7 g! s1 Q+ `7 ~. |/ I; @6 K

    8 [- z1 F+ T% H" R) z- g. f三点重要:1 u; z' Q5 Q3 v# z: l- u7 \2 E8 r5 k

    " D, P* S9 y$ d# m! O/ Z7 m窗口内是什么?8 ?+ v) X; D& a; g
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。2 O5 j! l( b1 n, O
    如何移动窗口的起始位置?9 a9 @/ g- ]4 C8 U& N$ k4 D" k5 e
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了3 }- i: P  a) i8 v
    如何移动窗口的结束位置?
      F/ g  R/ l: x6 L8 U! g& W: p窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。: k+ B# }0 T2 g* T) H7 T

    - w" i5 j+ \2 d2 A, a9 P  c+ P 代码如下! ]( R9 G9 H  p# T4 t! X/ F
    / `/ ?$ B; Q1 K2 h7 R7 L2 E
    class Solution {
    * s% G1 p9 w( t' X2 ]7 {public:
    # m( o1 \$ h* e3 l    int minSubArrayLen(int s, vector<int>& nums) {
    - t  t8 K6 d9 F; I, p$ O  U( ~        int result = INT32_MAX;
    % y3 _' V1 M7 Q( a& W2 J; ~        int sum = 0; // 滑动窗口数值之和
    : V6 _3 X. \% y1 H" b        int i = 0; // 滑动窗口起始位置
    ! `6 f! P6 ~' R% E        int subLength = 0; // 滑动窗口的长度+ B6 s, G$ M! Z# S+ R5 N6 S
            for (int j = 0; j < nums.size(); j++) {
    ! o6 @7 e; B- s$ H7 U6 h            sum += nums[j];4 o5 N: G7 A9 F
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件9 s- S* c, A% u; k4 d' t
                while (sum >= s) {' K9 m2 i* C+ Q1 m* Y7 R% m; G6 L
                    subLength = (j - i + 1); // 取子序列的长度
    2 m5 r& n" X# N4 h                result = result < subLength ? result : subLength;//一定会赋值
    2 G, M. X' d" y                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
      T$ _! H( [. \+ C; X  P& ^7 U            }" j0 B7 X8 @( C: l
            }
    8 j& a9 e( [, _        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    ; ~6 r1 N" ?/ l        return result == INT32_MAX ? 0 : result;' e$ [5 Y. w. b' j1 W6 k
        }
    5 @. K; Q/ ^1 s};
    : L& w" y& s1 L5 q: {$ H$ F  _6 c) E7 o9 a
    一旦大于,就减去左区间的值
    8 Z6 d7 k% \/ ~; Q$ G  G7 |! v3 g. g2 u$ v
    5.最难题螺旋矩阵||; G' {( u( d# c
    模拟顺时针画矩阵的过程:
    3 Z! {3 t' s8 ^/ ~+ y
    2 u6 p1 @7 n; R: p) }填充上行从左到右' M/ R" F3 Z9 G. L$ {
    填充右列从上到下
    6 Q: h7 X8 ^# m: Z% J0 V  A填充下行从右到左
    , w- O9 J3 w' `# k  J/ f" P填充左列从下到上
    . h& C" A* J! v; V1 Y6 t! T由外向内一圈一圈这么画下去。8 ~9 d( d; \5 G! `
    8 P6 A+ Y3 ]1 ?. \( U1 K0 G
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    / M. {, w, w8 T; V$ p$ ?  ]" b4 C; O& [" Q' U4 A0 _
    , T6 p, u/ j' {! T& {" O

    : b: }8 A0 A" m- G' x- x/ s" t  T6 M/ O

    * h" t9 b4 u" n6 w4 xclass Solution {
    7 w' \( t$ x6 _4 S$ e( R' V4 Npublic:
    , Q4 z9 \4 p3 M, W! ~3 @$ f, W) `    vector<vector<int>> generateMatrix(int n) {3 p0 E0 e8 H4 N
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    " \* m9 P$ A0 Y7 n- r- P$ _& w        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置& V. b- i! i* Q8 o0 D* v8 |
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    1 O, y* D" G5 o1 k        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)" o, y0 ]4 T# x& d; B! q' i9 G- n
            int count = 1; // 用来给矩阵中每一个空格赋值' D3 M8 I2 e7 m( d" w6 b
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    + Y& f1 @1 E+ ]* i        int i,j;
    - l4 }/ m% p5 y  W, {3 g        while (loop --) {
    ) R7 U5 c* W2 K- X$ d# O3 C  `            i = startx;
    ' d/ W. C  l& {9 M: ]/ A/ v4 q            j = starty;
    2 C' z% \8 Q& e9 `
    ) d( \6 Q0 J- R/ e* i' s: D            // 下面开始的四个for就是模拟转了一圈. P4 z/ \0 |2 v" v' B) G7 M3 x
                // 模拟填充上行从左到右(左闭右开)6 x; g- h: D. S  B( N  S  O
                for (j = starty; j < n - offset; j++) {5 n" n' H- s! U( j# \
                    res[startx][j] = count++;
    5 r6 A+ O9 u$ v) h. @9 ]: P; ?+ s; d            }$ Z6 m" Q- P! D( I6 ~! E
                // 模拟填充右列从上到下(左闭右开)
    $ f" Q# ]7 |5 u" ~$ y            for (i = startx; i < n - offset; i++) {! V" ]- n3 |) k# i# w
                    res[j] = count++;8 ~# o7 r( ^2 Q/ d4 @7 d: n
                }" h9 C8 U8 ?+ V
                // 模拟填充下行从右到左(左闭右开)4 O* I  G# _+ N6 e
                for (; j > starty; j--) {8 C4 Y! y6 H2 D' z3 u5 a. P+ ^
                    res[j] = count++;
    0 C2 f  l  I/ p            }; X4 e$ s1 |( N( Q
                // 模拟填充左列从下到上(左闭右开)
    ; S& P! e$ N- p7 d& v9 m, Q            for (; i > startx; i--) {
    . {' A) ?$ j( i, ]# h8 e% Z0 L                res[j] = count++;1 [5 }# \$ B0 i
                }
      T2 C3 |( z% ?* U
    ' J3 P0 n5 D9 N6 }            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)0 N" ]0 x" t/ I( V
                startx++;
    $ K7 E: \4 k0 I; d) M# }+ D            starty++;( s4 r7 E. r5 S" z9 z
    ! n- `- |4 y2 ?. y& `
                // offset 控制每一圈里每一条边遍历的长度! B2 l$ }+ ], d; {: @  P" m
                offset += 1;
    ; V8 v" y  ~5 c4 z6 g9 k# [: P  J        }  e8 Z8 b4 v, p4 P) p: X9 L
    / m# {, l3 W/ [5 e6 A! m; i, _" x# K
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值+ M8 R4 y, h# I
            if (n % 2) {2 @9 Y: u9 \1 R% c. d  l- O: F% J
                res[mid][mid] = count;
    / k8 s1 h8 b) p8 Q' s        }
    . f! s" @& f# g( V        return res;2 O6 D0 V7 D1 ]6 d
        }
    5 ~7 \' t; T& [5 U* C};+ n% c" X, E8 g% a& o
    ! K& ]. s2 P& ~' e+ f& \$ \% B
    ————————————————
    ! X4 f8 w/ I* H" e; `版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。0 @1 ~" ]& E9 L" ^0 q3 z6 O
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    $ w' c; Z) z  o6 g+ Q1 v
    3 `+ s- h+ }( |. F- {6 M" C2 S; k$ Z+ x
    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-6-14 19:42 , Processed in 0.740541 second(s), 51 queries .

    回顶部