QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2004|回复: 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
    数据结构之数组练习
    5 O! {% c" X9 p" [1 W8 f$ @1.leetcode704
    * n, |; w. U# o# U给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。; V5 I8 t7 @( Y) h+ Z  ~" I) b- h2 h

    " D$ M5 N8 m5 T$ K1 x+ z题解:升序 数组7 g: @3 X$ I0 L, z% p1 H

    & `" O% r- d. ]0 B) x1 c方法:   二分法
    " E5 O3 i& T+ C( [; ]5 w5 d
    . u  t+ Y3 o7 K3 ?思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    # i* w2 w) Z* u* u# d
    7 Y( H* u  @5 c比较nums[mid]和target的值:
    , ]9 E9 k7 c) U) k/ s- p4 W  `* o& r1 C% Z4 q8 l6 P, L  x
    如果nums=target,则下标i即为要寻找的下标;
    & i  R# J. `; H5 s7 E4 j
    ( i5 a5 ?  W/ l0 d; r如果nums[列]> target,则target 只可能在下标i的左侧;6 o+ O0 R" U9 |% V
      N" w  W$ k; R/ P: i- J
    class Solution {
    6 J" v* S& {% `- V. L- B1 x  zpublic:- ^2 R5 L& g# D; d4 ~
        int search(vector<int>& nums, int target) {: G. V' @9 x% c/ N
            //区间[left rigth]
    - _: s& _. q/ \  A/ r1 a) A        int left=0;. i: E7 B! }! l/ |1 A
            int right=nums.size()-1;
    . ]5 u, ]0 Z0 I6 G9 }: s) s        //结束条件 left>rigth) a/ `  L& G# ^* i" X( R
            while(left<=right)
    ) N, m8 J- ]+ }  F0 {) @3 `        {$ h" t" t( ?( p2 N
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]6 t8 R& e5 ]& X& t% S
                //[middle+1 right]) P8 o% F( V0 B4 p1 B( W7 b4 D- Q
                if(nums[middle]<target)) g! a2 @7 j3 W/ V
                {
    1 \9 g. G9 l& W; s, T                left=middle+1;  H( r" C& A' I; r% D
                }
    , ~7 K+ k1 A( E/ P  O' _            //[left middle-1]
    & K& Y0 J. z  S+ w            else if(nums[middle]>target)6 E  v: `( S; E
                {
    - c8 z& P9 U' F; z5 G2 I                right=middle-1;
    . K1 |& ~$ r5 |$ \( `- o; w" Q            }
    ; ]. k1 f, h( O9 {            else{
      \- ^$ P( \% {6 R8 B5 c& U                return middle;
    0 [& X/ k+ M+ X/ \) N            }  h. Q+ h- t7 [+ l9 ?

    ' B+ C% N6 D9 z- E  C        }
    ( D  d6 s+ V6 C$ S& P0 Z  i        return -1;* R2 L- b# m% p
    ! m7 A7 d: Y  H6 W- x3 H
        }; S$ [/ k$ P5 Z' p6 S% p/ m+ c3 h
    };
    1 {/ Z$ Q( T! v- u6 R# n1 @3 O
    1 l4 |  V2 l0 W, |2 ]5 B注意:
    # m* _; P5 \+ z& c
    # J; m& b; J9 z/ Y* }) D( G0 u8 f(1)设立区间为[left, right],终止条件为left>rigth  a4 b6 c, R/ U' Z7 p' L# w) B
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)2 W* e2 [! O: z+ m
      (3)    通过改变区间的左右值;复杂度logn( I$ n7 B4 N- u4 c% D: s

    2 S1 d( p/ I4 J& Y5 z! a. Q2.leetcode 27移除元素% i& w% K. a2 J0 V
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    $ J" i+ B9 }1 X9 q
    4 T# v3 a0 a( B/ X, y% {不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。- w: M' l! t/ ?/ T' P
    / @, t7 e/ T2 n$ e& C9 \, x2 U' ~4 x
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    * `+ C1 w" U% v: z2 W3 z! l5 w* m3 ~" m3 r8 Q; H
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    ) y- f+ I- @! D/ I5 e, d  P% f( U0 T1 I3 [
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。% R" ^- e: N  ]+ {8 Q: K; z1 b. f

    $ h8 q8 @9 H8 \思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    # A7 H0 i2 c* W0 C) H; Y
    . y8 q( H! t; v$ s# K, \方法:双指针0 u1 P& H) H# J+ Q# k

    0 l$ `: I" `% d! ]3 |class Solution {
    6 W4 K4 J5 K/ P. F, c7 Apublic:
    ' b' V. C; l2 b$ y! J- Q7 v0 G    int removeElement(vector<int>& nums, int val) {
    $ ~) e7 e& a( Q( H) O1 h           int solwIndex=0;, T7 i4 M: Q/ R7 t0 {' h( b% V, }
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)4 X0 E+ A# n# u; N" f$ X' L
               {1 o8 p' s3 \  D2 p+ }
                   if(nums[fastIndex]!=val)
    ( U7 v! a4 K6 o/ E+ U5 y               {1 Y) S7 h5 \5 Y) X0 _. k* u7 s
                       nums[solwIndex++]=nums[fastIndex];
    . E# N9 O6 `8 `, M8 b+ _3 x               }! x# W4 T9 I/ Q  A. \% Z3 ~7 T
               }" ?; D. \( W9 M  Y% u) @
               return solwIndex;
    , X- m/ l* R& ?  W/ o. X    }
    9 |5 X/ Z+ j" v};
    ! [4 ]3 |0 C8 A" `' o6 A/ Hsolwindex:用来覆盖2 l+ q4 v) x/ ~0 U4 U

    6 A( z/ T6 q* @7 Q. sfastindex:来找删除元素++
    * H) f0 c( F; q( V$ P9 @! b+ V) q2 _7 A
    3.有序数组的平方
    - T$ o1 r- ?8 z9 o8 [& r给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    " X6 I6 T! I+ D' |7 D$ |
    - j4 F  p4 |& ^2 D1 u% u数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    ( |1 F# C. Q% s5 k/ [3 v
    * m0 s: \5 g, x# l. k1 _3 J那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    ( P* J. K' }1 ^+ y; V$ g9 }9 }" g
    1 ~' ]% ?- ?' O* S/ V5 {" l7 o) z此时可以考虑双指针法了,
    * M) U' X. |" q. n: X
    6 t) P# o3 R! N+ pi指向起始位置(负数),j指向终止位置(正数)。0 D- |0 u: ?8 w

    ! W7 F( n8 N9 {1 }  _. ?定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。* [9 O9 A) [2 i6 M
    # [* s9 t) Z# D9 o+ F% j( b$ S
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ! e# d3 g0 X0 c3 G3 x* h& S6 l/ H6 n' z. L0 ?- o4 w1 S  u
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;. I$ Q" x) f) ?, F

    + N# b9 h& c; _" r; S+ `0 Kclass Solution {
    1 J- j, k0 `, U8 y3 ~8 P; h; ipublic:
    9 G, V3 W9 t) U: ]7 F    vector<int> sortedSquares(vector<int>& A) {
    ) ]# a3 y$ N# n9 z0 t7 f3 ~* {        int k=A.size()-1;
    ; W& D$ r- V7 G6 ?        vector<int> result(A.size(),0);
    1 i- V& N' j: c" W: @        for(int i=0,j=A.size()-1;i<=j;)
    & @5 m" U$ y$ H        {
    . Z! z% }5 M1 v) n. Y" A+ X8 @            //遍历一遍2 o5 w1 A- ?6 p( y2 M  l
                if(A*A<A[j]*A[j])  m$ Y5 q8 i- \6 U! h
                {
    ; Q( X; _! Y9 I                result[k--]=A[j]*A[j];0 W  P7 _9 O- e$ O
                    j--;
    ' Z& N6 p5 T: a8 e0 Z- A: y            }" n1 [! b1 `  n1 B
                else9 f9 G% p4 I( D7 @, S. a% u
                {# P/ V- I- X4 Z2 }# T! s+ `9 C5 e
                    result[k--]=A*A;9 V0 u/ e, r4 P- E' P
                    i++;7 g8 w; r  V2 H
                }4 W! B% L  }; e+ O, u
            }
    8 y3 g; W2 {( h" z; s0 q        return result;
    5 [1 ]5 e( R7 ~" q) ^
    2 s# P, ]( D3 \% H4 w. i1 r    }
    0 {  r2 S5 a- x1 s};
    - q9 L6 v) F$ \5 T3 Z# ]/ k
    / ]" v4 J6 O5 z$ ~6 }  M  ^4.长度最小的子数组* ^: e4 v5 q+ X8 M/ `8 m
    给定一个含有 n 个正整数的数组和一个正整数 target 。+ B7 g2 i, }0 @$ |, b' R& S
    ; u! o) u4 k; x; C
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。# i: m5 b) M  m% ~9 W$ w9 z

    3 K" y: D5 m% s0 f& L' ?方法:滑动窗口法( u2 U1 a/ C+ n  p2 S0 P& [

    . J" X  G2 p5 N- W" Z就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    & Z* J  N! q0 p, x
    ; e5 D/ T. A" X7 f6 j: ~& L& Q三点重要:
    % \/ Q! r8 _0 [& f( M9 p* M  d3 j
    ) C" N( C, s) G9 m3 F窗口内是什么?
    2 L  i- I" d: B+ r8 ~* z窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。! ~0 f4 x4 ?0 K* v$ Z) u0 N6 k
    如何移动窗口的起始位置?" l  `( T3 E; h1 [) c$ X1 v( f
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    ; ~- `- d  [- q如何移动窗口的结束位置?
      }, i9 w; E; L' R窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。, _' g: {/ Q* B% L" V% ?7 ]" S$ ^1 [
    ' @5 Y' r) w" F1 m
    代码如下& A1 H7 O. O* t

    : X. ~4 I- z, X; q7 v; [* yclass Solution {
    " O  p7 i/ y4 K  U' F$ N9 A% Xpublic:8 R% s, {. j1 r4 m/ P
        int minSubArrayLen(int s, vector<int>& nums) {
    2 o3 Q2 Q+ c! C7 I( u        int result = INT32_MAX;! y) F9 l# {7 z1 n
            int sum = 0; // 滑动窗口数值之和
    5 t- k& {. X: \' V6 a% z8 g; o        int i = 0; // 滑动窗口起始位置
    / W' v; z/ J& o        int subLength = 0; // 滑动窗口的长度4 w4 a. f6 T2 m# q
            for (int j = 0; j < nums.size(); j++) {  Y" k% ?8 j3 d. P, g8 ?
                sum += nums[j];
    ( B' Q8 v# e6 ]# a" }+ B$ ?            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    8 R. D/ s8 W  q            while (sum >= s) {" f/ `$ m5 F( v/ }: g# Z
                    subLength = (j - i + 1); // 取子序列的长度
    7 y8 S" X3 g, p, U                result = result < subLength ? result : subLength;//一定会赋值- a9 U  ]3 ^5 `* X
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    " j6 s- C9 g; q4 N2 _5 K/ T+ S            }
    7 b& j5 k3 T5 F3 n        }
    ! Z. s/ x' w# L! ?- B% t        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列! f% C: _- y1 A2 O
            return result == INT32_MAX ? 0 : result;0 m4 Q) w0 g8 E( K4 W
        }
    / `$ W# [0 ^- V" ~: V$ E};; R. R# B8 ?0 l$ @' W! F5 C, ]

    ' c# @5 @3 ?- M% R1 ^' K一旦大于,就减去左区间的值) V1 S! V( E  I4 G- p$ w# n

    , o% q- A. _# m$ b+ b5.最难题螺旋矩阵||
    : f4 P  c- C9 y% ?! a1 ^! L模拟顺时针画矩阵的过程:
    3 n# M3 ]- X  w- M1 C$ E, i
    8 \' K2 i/ v6 C; H填充上行从左到右7 O3 D  F( H. [0 i
    填充右列从上到下
    5 {9 ]' E; r9 T+ R填充下行从右到左
    & T9 D1 d1 J7 ?; _0 m& [( D  i填充左列从下到上
    6 O; T6 x, x5 `- V" Z1 V, q由外向内一圈一圈这么画下去。
    4 l: f0 W& I. I$ W" u/ L1 p) B$ T8 [/ D/ P* H2 N) s9 R% M1 {4 U
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。1 x) n0 ]+ Q9 x$ ?) a, E* ?4 P$ L
      ?$ n. L3 F0 }4 y, y

    * y2 K- I: a+ D1 e* N
    7 Y& x) E9 X6 R* A; Q% O( z
    % E6 v- d8 b  C- K$ o0 {- z. _5 c3 P, d& A) Z/ B
    class Solution {
    ' U" P! g6 B2 V7 o0 u4 ~* O' Ipublic:
    * [1 C9 {( V) e$ Q7 U% _    vector<vector<int>> generateMatrix(int n) {3 r- X, i( j1 h: L" U
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组% L2 p/ @" |) n0 g& b
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    ; U% {. x5 |' R. Z        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    6 D" M& |/ w' F1 P        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)3 \$ S" e6 M: c
            int count = 1; // 用来给矩阵中每一个空格赋值' L4 B" j5 y& m/ d) F- V, f
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    8 z2 b/ P+ p$ n* [7 D  B# m+ L        int i,j;
    - U8 j) V. G# C3 x/ ?8 {        while (loop --) {
    : s3 E) V! j; a4 V) l. U            i = startx;  t6 Z0 F, q) @
                j = starty;
    5 a6 W8 c! G  q  w* M& t) |; h" ]/ {
      F* H$ P+ A# |            // 下面开始的四个for就是模拟转了一圈
    6 M2 Y: A7 X/ o, M6 g4 @% E            // 模拟填充上行从左到右(左闭右开)( r# Y+ d* ~7 a; d6 I; q4 A+ [# M
                for (j = starty; j < n - offset; j++) {
    ' S4 Z; A6 ]1 ]                res[startx][j] = count++;4 A# T1 L- k: \2 {- V+ B
                }
    1 N6 U& A) ?- q! W            // 模拟填充右列从上到下(左闭右开)) b% M9 T5 {4 {& }+ X
                for (i = startx; i < n - offset; i++) {  |$ n7 _. z% M" v% r7 C- S
                    res[j] = count++;5 n' s( y6 E; _9 i" H9 g# |
                }8 ]6 [: S5 y3 k4 t# W& c
                // 模拟填充下行从右到左(左闭右开)
    6 R9 {/ O) ?0 W) z' p            for (; j > starty; j--) {
    6 z7 A4 m. _: e7 [                res[j] = count++;
    / U2 f' `; U* v' f: L            }, w; Y- \, b/ i9 ?: t5 m1 I
                // 模拟填充左列从下到上(左闭右开)
    ) t& N+ h1 y& G) `( j& h: H' P            for (; i > startx; i--) {
    . Q3 q* l4 s5 m1 r3 {% h                res[j] = count++;
    1 O; ^  e' u" o            }4 @1 v& J% |& I2 p( a8 x, l9 a

    : H8 i; q, h* P. Y            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    $ U9 p0 L1 d4 e2 a            startx++;/ g4 y7 k% D/ z5 w9 k# k2 N- Z* [, l1 c; p
                starty++;
    4 ~! s' F+ Z3 j- W6 K$ F4 l/ d' j3 _
    % h* J) Z2 J8 l! k" t8 o            // offset 控制每一圈里每一条边遍历的长度  Q% `5 |% Z% n2 o4 p0 a9 s: X
                offset += 1;" ]2 S8 L& R* S) T
            }
    $ T9 m, x/ h* e; N8 e# r0 W* ^& x  V5 |& s4 E% T, U" R, _( \' r4 s
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    6 f$ O0 _* p( W# G3 U1 C        if (n % 2) {, F. A+ Q1 q# p
                res[mid][mid] = count;
    - M. v2 V$ ?. x4 V        }9 s0 l# @4 L& X! z+ @
            return res;: ^) @% O) O8 X; [- j3 Q) T% A- Q3 m
        }6 ~! Z* K& n& W$ @  n8 U/ e( F8 S( Y
    };
    # y. n# c: v, Q5 _2 I6 i+ b& H! K4 U: }8 r+ b+ j
    ————————————————9 B( c5 p0 p  O! }
    版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。% u7 h& @. i$ y8 ]
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039! `1 ^9 q: P# I9 G7 k

    2 Z; n! |# C4 f! p5 d0 b0 ~: t6 [/ F, b; z, x5 V
    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-26 05:14 , Processed in 0.256829 second(s), 51 queries .

    回顶部