QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2014|回复: 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
    数据结构之数组练习2 e* G2 N+ C8 D4 l3 p3 l
    1.leetcode704/ G* u" D5 I- x3 q  D+ C3 a% S4 p, X
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    7 [) n2 ~3 t8 G7 ?0 C" N9 T
      G8 t8 f' F. k5 t题解:升序 数组0 E, H6 l. ]' m- O, H0 t1 h/ B
    6 O; F+ \% m- f" {' }8 r2 A
    方法:   二分法
    / w$ ]- d+ {+ G  n& x" C' C% E& \$ \( s2 f. f* C" Q
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)4 A3 D- ^$ G! l+ n+ T4 R4 a

    - [( ?- U3 {% w$ H% |2 a比较nums[mid]和target的值:0 N! g% c3 U. |; k- O% U6 W
    4 \1 G* ~8 p! ~* e
    如果nums=target,则下标i即为要寻找的下标;- k, `( F! [" C" ^4 k6 m8 M: s

    2 h* N, H) x3 l! a' M5 y/ E8 M如果nums[列]> target,则target 只可能在下标i的左侧;
    # v/ V/ d  b0 N! D
    4 J6 H: B2 k+ G& ?' H& g! Iclass Solution {" u- ?. d' [9 W( L3 Y
    public:
    7 x; q# {# b# m' e. ^% D0 t! Q    int search(vector<int>& nums, int target) {
      ^, Z) P! O  j5 h        //区间[left rigth]
    1 W2 [4 O* J% M2 @        int left=0;: S) b' v" r$ v; r% j5 x8 y: U( @
            int right=nums.size()-1;8 n, s9 T2 i) T7 @
            //结束条件 left>rigth
    0 y- ^. c) n, V( h$ e        while(left<=right)6 P& }7 l; p- C9 p/ F
            {
    / o3 i2 C% r, }+ ~0 G2 f3 r6 {            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    5 |0 S9 b( e( h            //[middle+1 right]
    ; x; `* ?9 l: g/ Q& f: P- a            if(nums[middle]<target)
    2 e6 n2 X" ~, u) t            {
    4 _- ]8 A' Q+ c, [                left=middle+1;
    0 G) l8 x1 p7 [. c4 c' y            }
    & C$ d0 a0 s# b' j  g0 u$ b: m            //[left middle-1]
    * H7 |  f5 }( C) u# D8 u            else if(nums[middle]>target)7 O' a5 h3 c2 F: C! v1 {! E$ e7 Z( O
                {
    % G( z& w8 \' G+ z! F+ M: `                right=middle-1;
    ' p$ u/ @% m# E+ n; O            }
    & q4 ]/ D5 T$ Q            else{
    8 m( c; F: v5 c                return middle;7 n' H2 W" m; _- j' S
                }
    2 `# j' F6 S8 e( ~" |8 M1 c, P& y% Q: Y
            }- [5 L" D# |- N% B0 B+ p
            return -1;
    2 u& Y- {8 C0 k- ]0 h. v8 @* f& i7 S6 C
        }
    ) P; j2 |% a! Q& J" x5 t' ?};5 ]0 l1 w( p& F  F* G0 n

    * D& f# L; Q2 S+ x2 k* Z  X注意:
    ! Q5 n) B, N, \; q+ k3 x7 Z+ F% w! \$ ~& t! z5 _
    (1)设立区间为[left, right],终止条件为left>rigth' A/ L1 p( w5 L
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    5 F# U! Y3 o$ Y: m2 T5 r5 ]6 n  (3)    通过改变区间的左右值;复杂度logn$ K2 l# e" y/ j9 y: B* H  d8 Y7 d
    ) g3 q9 M7 ], k0 x, E
    2.leetcode 27移除元素
    5 C5 p' z: n7 J0 e4 c给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    : W( Z- [; d4 J2 H1 `" r
    0 K) x, |3 A! j2 D9 `# I不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。7 i5 y+ L" [( w$ N; k; C" \8 |. h
      o8 t7 ~; [4 v* l! x% z1 }
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。& c& ~+ N4 t2 \; ]4 ^; A: {% r2 B; l
    * l; R2 Y, y3 F/ ]* G6 R: v5 [
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。0 v3 g# n- b& m* a+ k6 {

    ' a0 @8 G8 z$ @& Q, V4 S示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    7 W& B/ W' E* B5 w0 d+ T# i+ x1 b' u6 G7 W! D7 l8 m
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。1 I' {* x: [# ?6 ^3 L

    , k* e9 e. X  q) j5 a8 L方法:双指针
    & [4 w' B3 U$ t# U% Y& W
    - ?6 Z  B4 q9 {( Lclass Solution {
    5 C0 c$ D& l3 f7 o/ ^/ [$ Jpublic:& X/ G0 C1 y& y+ c# S+ k2 [
        int removeElement(vector<int>& nums, int val) {! H! ^( t* d7 Y
               int solwIndex=0;
    $ k4 g: c6 i! T9 K1 U- ?           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
      J' x# G, J1 {0 ]           {8 l. v. _( Q+ P! v
                   if(nums[fastIndex]!=val)
    3 L- N1 j1 R$ ?  c8 v               {3 z! H0 }. T& R& {
                       nums[solwIndex++]=nums[fastIndex];. A3 F# d8 W$ w6 I5 J; {2 D
                   }' H5 u; m! u  F" N( n4 y+ V. Y6 S
               }
    3 T3 G: z# Z3 r5 H/ u           return solwIndex;
    % P+ \  m. Y# ^. q: `2 x    }3 b; @" K  e1 b" O0 g
    };) P3 }! L, L( S! f/ Y" _
    solwindex:用来覆盖
    ' K7 e; p8 |1 r! g
    ( d) |4 c4 v, {fastindex:来找删除元素++' [# L% Y8 }# X. k8 z

    ; ]7 k1 s6 S/ {3 D+ R/ J+ O3.有序数组的平方
    1 n) H4 l+ X6 ?: |9 T给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。7 ?5 K% R4 _* g& `# w2 C
    ; M  h* s) Q" p  C7 K
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    8 F% R" Z' k8 e) J' h4 R3 K
    * o+ p" ]# |! B* S  I- R0 ^那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    4 a& {) {2 A/ N# T. [& {0 V9 X1 y* r& S. n
    此时可以考虑双指针法了,
    4 v9 S/ t( Q9 ~) u
    % b4 V3 G- ^7 o* p9 B; V$ F( di指向起始位置(负数),j指向终止位置(正数)。
      Y7 N; A2 T; ?- v! U8 j- S
    + y% C8 @2 C# L# |定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    . F) r/ V) C) |! h, \4 B" b% c& Y8 U. g" l* \3 {  n4 i
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
      N$ p$ X: B. k+ R- J2 a2 k
    ( R+ W9 M; i5 J如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    " C: ?" _, G/ l
    4 j/ Z4 M3 j+ H5 e5 \" l6 I8 Oclass Solution {
    1 W9 P- K4 C  i5 dpublic:
    6 ]2 s6 V2 o0 k' o% D    vector<int> sortedSquares(vector<int>& A) {
    9 f+ b: B; k7 r! O7 ^# j7 u        int k=A.size()-1;
    1 F) U. q9 p. ~# D        vector<int> result(A.size(),0);0 G. P3 q' Q  O, V/ V- {
            for(int i=0,j=A.size()-1;i<=j;)
    # M4 F2 v( \" E$ N8 D        {
    * {4 f% Y8 Q: g( ~6 Y2 ~            //遍历一遍
    " m$ ?- [' Q2 f( Q5 I) k            if(A*A<A[j]*A[j])
    , w6 n( c" ?4 F9 _: e            {5 D, }! k- l# E) `9 n$ H
                    result[k--]=A[j]*A[j];& Q) w! J. ^% `  R
                    j--;
    3 g  p6 C8 T0 I, _5 j4 X            }: D5 Q/ J, ?* E  \0 u+ e
                else
    9 d4 t6 P$ o# h6 r            {
      A- F3 A8 f' {: p                result[k--]=A*A;6 K& S" I/ f+ U
                    i++;4 f- `- f3 T. r7 h# }: z9 A' {' p
                }$ Y3 L9 t+ @1 W/ d
            }+ x: {& R% a- s2 |5 w
            return result;
    $ o1 ~6 _! O& M3 t
    3 d- Y) n  E; L; g1 |( ]    }3 i  y2 q1 ~4 Y- l
    };
    4 j5 A" G3 w: p
    ! u) c; c8 g0 Q. }8 W, x. T4.长度最小的子数组2 v9 |7 J7 V, }
    给定一个含有 n 个正整数的数组和一个正整数 target 。% o8 d9 H; h. T3 m: u
    . {+ o2 H( s) V& v
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。; H0 Y: i, O1 M+ t+ g& g- J+ L
    * {2 y6 T7 b: Q3 U! \2 [
    方法:滑动窗口法
    3 x1 O3 a1 K8 F) [- b1 P0 `! E+ z
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。( Y' x+ d( s% C# n6 U9 F6 f2 V+ `
    % Z+ x% n# A  q
    三点重要:
    % j, ]- T  N+ V- S$ K( y! A: a4 |, G- }% a* x
    窗口内是什么?8 E. n# y7 o- x; T6 _( Q8 R0 Q: a
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。4 F3 c% A& T$ n/ P# W3 k
    如何移动窗口的起始位置?0 G6 p6 Z/ \# I; A
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    2 ?; }2 F/ J& a4 q如何移动窗口的结束位置?
    8 D9 W+ f0 u  s1 a$ L( N' A窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。0 o2 f% x. t1 r7 ]6 Y# U
    * D- Y' |  ], L3 V; m# E
    代码如下
    & z* A9 n) `) j' o1 M) x
    ( R8 P! J( r0 ~! W5 iclass Solution {
    ) A5 z0 h1 g/ I; cpublic:
    1 @3 r( P3 n8 E& r    int minSubArrayLen(int s, vector<int>& nums) {8 g5 e  J+ ?. w% x: I9 r  ^2 a% q- O" b
            int result = INT32_MAX;; P6 `! Q) W: E5 m) ~; L. C( b% E
            int sum = 0; // 滑动窗口数值之和
    : s3 q5 z1 u' ~8 J& L  F. r        int i = 0; // 滑动窗口起始位置
    $ a" V; o1 l9 ~4 `! n% W2 U        int subLength = 0; // 滑动窗口的长度' ]" b1 o" j  f3 O- _' s4 d
            for (int j = 0; j < nums.size(); j++) {
    $ A; T1 e  }8 E            sum += nums[j];
    & {' Q: {: k* S6 i: t: `            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    ; Z. }7 v* T# y( V, s9 s            while (sum >= s) {
    # u8 p! i& P; K- Z: ~1 A7 Q; m                subLength = (j - i + 1); // 取子序列的长度
    ) [' O( w1 L" v! m+ x4 X                result = result < subLength ? result : subLength;//一定会赋值
    5 O9 r' u' F+ f) m8 U  X  u6 z0 H                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    ' i0 @( `6 e# u2 Q8 Q            }0 ^3 k( e9 l. ~* B" Q4 o' B
            }+ F# r' L" M% e6 t
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    + X  p$ w# l: T% w! {5 J        return result == INT32_MAX ? 0 : result;
    $ a& n7 x# k* V# C1 Z! r; c0 ]! z    }! k) q4 A$ V" r" s$ g% ^- i4 I
    };
    - e+ A$ N( z# _
    + ~3 `5 q. e. M8 K9 o一旦大于,就减去左区间的值
    6 m/ [2 e8 }. E/ T9 W- Y; N- C# Z2 U  |+ Q
    5.最难题螺旋矩阵||: }7 b! H( J: v) p& N9 c
    模拟顺时针画矩阵的过程:
    9 x  l* ~% R9 T/ O. a. o
    # D% Q& O+ J. E( _# _: O填充上行从左到右
      V8 z& @4 L! ], S" a4 @填充右列从上到下5 Y2 l& R, Y! J; N9 F8 E. v0 x
    填充下行从右到左
    ( D- O) Y9 V0 ]5 z填充左列从下到上3 x* G6 F' H' g8 j6 _
    由外向内一圈一圈这么画下去。& N0 L, l% |) {; }

    . T3 w8 P6 P! s# q5 |这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    1 z& U+ }# t: q3 t1 q- `0 }8 C
    # E$ |9 L. E: ^( B8 A; a. X& ~% P  a0 W0 H

    . {6 q: L9 ]% O) b% A5 p$ c3 I3 N. S1 D
    - x/ K0 }7 [' g
    class Solution {
    : h3 K4 D: L! A- C6 b! Y' Opublic:5 K1 D+ e% t5 N6 ]7 @
        vector<vector<int>> generateMatrix(int n) {7 U- x% B+ b( v8 ~6 S, H
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组( K4 p* S7 B+ V% [! q
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置4 x9 z6 p8 b: Z! i3 m. q4 @# |
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理7 r! {" s! J$ @: l& {$ B; f
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2). {7 k/ y" Z4 A/ p% ?: M
            int count = 1; // 用来给矩阵中每一个空格赋值3 d- J- R& W8 _6 D7 O' Z
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    " }! a& ~( `" s4 w        int i,j;  ~7 D* h. I6 f, \' v5 h0 m
            while (loop --) {
    ) H; g* o/ v- [9 c$ q# K/ z            i = startx;: X0 P) }2 f2 N+ X8 l- H
                j = starty;
    9 \: j6 S$ J0 D  L; l
    ; B0 A+ t- ?$ r4 ~/ L6 W  F! ^9 A            // 下面开始的四个for就是模拟转了一圈
    & `: M" [& K1 F9 F5 G) V            // 模拟填充上行从左到右(左闭右开)  l7 T' e+ Y$ d' s: N
                for (j = starty; j < n - offset; j++) {( L0 l; ?& P1 h5 j- R
                    res[startx][j] = count++;2 _$ D8 o: c1 @" c" r3 o
                }  V$ b6 x8 q8 z
                // 模拟填充右列从上到下(左闭右开)
    # Q9 ]" \/ F7 a$ T6 z8 |4 E            for (i = startx; i < n - offset; i++) {5 S5 h, o! j$ }
                    res[j] = count++;) L( ~9 j: `0 _7 g1 W  D6 t0 F
                }
    0 S2 w7 T. {& @8 K8 M3 Q            // 模拟填充下行从右到左(左闭右开)4 x: b% p/ Y- O0 O9 q) ^4 F+ i  @
                for (; j > starty; j--) {, T5 o7 F& d+ L" n0 B# [6 s
                    res[j] = count++;2 U" i! J9 m3 ?: \
                }
    . V$ H6 p! J/ y+ D- r) X            // 模拟填充左列从下到上(左闭右开), \4 s6 Z* c; p* M  B. `, r- S, L
                for (; i > startx; i--) {
    % F2 ^, @9 H9 `+ c/ s) a                res[j] = count++;  o* _& y. j1 O' @: S7 i" U
                }
    : s* Q# o& o& K: B" ]# k
    5 C! M9 ~, `& I4 Z            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)! g9 J! @4 _9 p+ L& ?2 S
                startx++;9 t" N- ~& w( |) _
                starty++;
    ! B+ C7 J. U" N' K: l5 C, p7 l$ x" L9 n' m: |# I
                // offset 控制每一圈里每一条边遍历的长度
    ( _/ m! o( z5 s9 U* o! y, Z, y% n; q            offset += 1;5 C9 Y, F/ Y6 D5 C
            }
    8 _& {" L/ a9 M! m6 n: j% \8 R3 ^, U* F' e: |
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值* T9 g/ b  q- [. i
            if (n % 2) {
    $ {3 ^; ^; r8 p& ]( z            res[mid][mid] = count;
    8 Z2 W# p6 ]  I9 F7 g7 Z9 {' ]4 E        }
    " T# w0 V, P& _        return res;, U! c0 f/ M( U
        }
    3 ~& v, W) e! U8 t: o- F};
    & R3 `/ f$ I# n  j/ @; R6 d
    8 @# Z. z( q8 _+ f* F. Y: X" h————————————————
    1 ?/ k0 e9 T2 b' Y, L' n& u: a版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。! v2 g% |8 q/ u6 U. D7 N6 D4 J
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    1 W9 V  n1 f" w. q- b9 H, ~9 M: q- h+ E: c, u$ |9 E
    2 y+ J- e# _; @- ~% }0 @
    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-29 23:22 , Processed in 0.381758 second(s), 51 queries .

    回顶部