QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2037|回复: 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
    数据结构之数组练习
    6 X2 j3 m- k- o. r" s7 i; Q1.leetcode704
    * E7 I, \: X/ E# N给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    6 S5 Z; a- i, P3 Q7 ]. K
    ' u: }. D6 P5 p( F. I' M' n# T题解:升序 数组; p8 V1 Y3 d; w0 l% g

    0 W; Z3 X* c4 L& ?2 y1 L) k$ ^方法:   二分法; ^) B7 X& N: D% G9 o
    : r! h9 h% _4 E7 f+ p# a' z- P; \
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    & P4 i6 F3 P% {1 Y+ O4 N1 K. r
    8 }' e: f- [$ @5 P比较nums[mid]和target的值:
    & {/ c( R4 ?6 w; l" {
    5 l/ Z% t, [; H4 B3 Q3 z如果nums=target,则下标i即为要寻找的下标;
    + M0 K( t5 l+ V4 q& f+ v5 g  x) O8 y* m' e) q$ w
    如果nums[列]> target,则target 只可能在下标i的左侧;9 G: Z) g& E) ]2 X  p# E2 c
    ; w" I9 T3 J( ]( J
    class Solution {
    & E9 r' j1 O8 v# gpublic:
    9 G6 `: _+ @6 O# \/ I    int search(vector<int>& nums, int target) {2 C  ^  J0 j$ u- h
            //区间[left rigth]2 I( T; p! p8 v; q0 T5 l& g
            int left=0;6 w  ]  u# y. R0 _# z, n
            int right=nums.size()-1;
    8 j' Q. t' Z7 u* D' ^        //结束条件 left>rigth, ^% w3 h8 |# |6 m$ E
            while(left<=right)
    $ f; ^, d& C) Y$ n2 b% c8 u5 ]+ c0 _        {
    . e  Y" I: a# Z5 B! P            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]& G$ z, c5 K5 U  K% @
                //[middle+1 right]
      K- [6 {% f  I, {3 A. P, [9 I/ R            if(nums[middle]<target)
    5 R  t4 x9 X  B; j0 e8 f& f8 Y            {) w, e2 p/ M+ ]4 V" A2 @+ Z- C
                    left=middle+1;
    - o5 M( h# l8 I5 d            }
    / L# O! Q, V5 ~% y1 _% T            //[left middle-1]$ c+ @3 Q) N) |) r, \4 `2 |
                else if(nums[middle]>target)9 D6 g6 Y; ], p1 B
                {: i+ P) y, P# J& X8 X3 N  ?
                    right=middle-1;
    6 X* J/ s! f& U( {. L* Y3 k! k6 K            }
    8 s+ ?4 w2 q) V( i# A            else{3 Z. @" _5 b2 e4 \. `( v
                    return middle;
      s  p( \: f( e0 H5 q/ |            }  W' ]/ M8 Z5 q: P

    , G6 f6 n2 k" G. s" f        }3 j7 V- n- e" B9 ?. l1 r# E% h; G0 N; q
            return -1;, ?7 p4 D% M5 o
    ' v& ]- M, e0 O' r8 V$ [
        }) |! }" T/ ]: Q: S/ @  w$ _# O5 U
    };
    . F5 t  W& o/ V3 W2 C6 ~' E- {+ M0 V: s# S+ v- Z5 t  z' E! g5 r
    注意:
    + p- G, {: \4 t
    # n1 i) i/ [' p8 W(1)设立区间为[left, right],终止条件为left>rigth
    , |6 B3 R2 n! i- G  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    ( ?8 N8 g. g% W: j  (3)    通过改变区间的左右值;复杂度logn
    % K# d: x6 C$ A- A6 a/ s- j) u4 K; A6 C! ]5 Q; B
    2.leetcode 27移除元素
    5 a, o! Z6 L# w- c. `给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    1 s, G# K! P: U- G1 e
    ! ^& R" \3 c& ?  {( S' d  `不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    & @; c" E" K! }  f9 G
    / z# E- P; y; w. y& O元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。5 B8 I  n" |: n' C! }% O4 p' u

    $ d8 {3 e3 ~0 H1 M0 V示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。& M6 \9 E4 j6 p- {

      z4 T" F1 W( y示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    ' b, s0 z: l; v0 I5 V8 @5 _- K0 y1 R! \- V' w& K
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    , E' X# J: `' U0 O$ a9 F3 M. k" a6 s3 Q2 w7 b) [
    方法:双指针
    5 C/ H% V$ l9 T2 ^4 |/ U8 ]5 z6 K* _1 x
    class Solution {9 T# A- L1 e8 {( G
    public:
    & l, {5 I$ D' i$ z    int removeElement(vector<int>& nums, int val) {
    ; J" C. X- }  Z% q2 B/ p4 }: c4 A           int solwIndex=0;" X2 D* H0 G: q9 ]6 \4 O* ~
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)* V5 a9 a$ {& ?0 y' ?$ h% `; `
               {! h# Q+ w3 y0 z2 z3 t* y
                   if(nums[fastIndex]!=val)# f; n# ?$ U% `* K) Z9 k
                   {, g1 S) i* k1 z8 g. U; g- B7 `
                       nums[solwIndex++]=nums[fastIndex];; W% u" [' @; H, I. m/ E$ ?2 P
                   }
    7 F% `% d3 k2 H6 z* g/ }, l# h2 u           }3 i0 i8 X# _" P: U% U
               return solwIndex;6 i) A! u7 R9 F8 }9 ~, ]+ [0 |
        }
    & h. H* e; _% `7 \7 Q# d};# p) W) F# d- e# B0 U
    solwindex:用来覆盖  X, [$ \( w$ h5 x8 T# e

    ; e% s- @6 B( y. r0 ]fastindex:来找删除元素++
    1 p7 y% z9 F& _1 |0 F7 j5 h1 }- g* M' f6 I, C$ A2 I( P- O, q
    3.有序数组的平方
    , v4 w2 Z" F7 h0 i2 y: {  z0 h给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    $ Y+ O6 V6 O% m1 |' C  O1 @) d( l: `
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。3 g" e1 ]( J" U* Y$ T2 w) b+ l) T8 P/ D
    " ?7 s$ w2 j- T  g) x
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    1 b1 g* O: q$ B, y% A
    0 x+ h3 K) V, {; l7 O& q3 z  [% o此时可以考虑双指针法了,
    0 R. X6 B+ M( i  R; z& {) r
    + o, ~, j8 F2 j1 li指向起始位置(负数),j指向终止位置(正数)。1 S: x# |# j& O( o- e3 e
    , z) H! ]" q: c; t9 ?! o3 ^
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。4 q9 B7 h. _; x. [; ~2 y5 N: F

    # e* p: l$ b" K4 f) G如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ( {2 n  L+ n8 u4 d" j2 u, H3 b! b. k$ K8 Q/ T( H
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    1 Q; G' ^1 h; }
    + _! r& J4 x! e% ~% ?$ u& j: q; aclass Solution {
    ' F7 v+ s1 N. n: D, X1 s2 Wpublic:
    # x9 z$ ?) D- p5 e    vector<int> sortedSquares(vector<int>& A) {+ e8 e$ z2 h2 K1 I+ B( P) _1 A( \
            int k=A.size()-1;$ p  `- j) d% K* E, `
            vector<int> result(A.size(),0);
    / @3 S$ I0 D! H; e, E! j        for(int i=0,j=A.size()-1;i<=j;)& e+ @/ \( [/ f8 L
            {
    1 c# N, _* E5 G6 {) ?% U            //遍历一遍6 Z% N% ]* [# M1 o/ }+ n
                if(A*A<A[j]*A[j])
    8 [1 p. l# t7 ~6 J            {
    ) O% @! T1 I' P1 \& x7 d                result[k--]=A[j]*A[j];
    ; M. B" k4 r7 j                j--;. c7 R1 o0 H* [  T  B2 Q. p
                }1 i2 ^% n! S3 E( h) e6 L
                else
    + A: b8 Z+ v3 x4 ^( o2 Z3 J) P            {
    # g6 h5 M9 m8 y- I1 I2 {" p; e7 ?7 r                result[k--]=A*A;4 Q: Z9 z) u: X% U
                    i++;
    0 z0 O& u5 H' m3 G3 e            }
    ; q  s; d- D, |) |* t        }% F5 j0 {/ W% p4 P
            return result;* V- ^3 n+ s  K" A

    2 v/ F! `9 q0 G5 I" m$ N1 ~0 n  k    }
    $ j+ G9 i$ E$ v! F};( M) x" ~$ T' e9 |

    $ B% b- V8 K: {0 |4.长度最小的子数组
    0 N1 B8 u7 U. }5 n5 B给定一个含有 n 个正整数的数组和一个正整数 target 。
    . H& q# }: Y2 f" S
    4 Q& s, s2 k: o8 b# y找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    " v% Q7 ^( ]+ I  B4 G; S
    2 s& K, X8 E/ V" M方法:滑动窗口法
    ! F8 S6 K& U, U& r$ p, Q) O3 B; ^' `
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    7 `9 v# N+ |7 a0 U  P; }( H* f5 Z6 k3 \5 v. w
    三点重要:  s. g2 P; r' ?- c3 S$ ~
    ; g' D) {' h3 d' q6 {
    窗口内是什么?
    3 L! Z. j6 Q) D' S+ z  w2 V' A窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    6 d( p6 S8 u1 m* Z8 F$ s% m如何移动窗口的起始位置?8 {! I, u5 t/ T, a/ ~
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    5 ~" y4 f; f- ^8 N+ ]( a5 |如何移动窗口的结束位置?9 h( }  C9 t7 {5 b+ q3 x# _! D7 _
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。% `& E8 R( R/ u; s1 l& _$ T5 S
    6 p0 x& i3 N4 ?, k! N
    代码如下
    : T; V: N; K0 T4 p( I2 h" o/ }; \2 |/ k1 {
    class Solution {8 n9 [1 [+ k, U4 K
    public:
    6 s9 ?6 i5 k4 q# s) q( m    int minSubArrayLen(int s, vector<int>& nums) {
    * A9 U' z  @; c* L7 G5 c        int result = INT32_MAX;
    1 R' I; f8 h4 h. C: s) r        int sum = 0; // 滑动窗口数值之和+ ]  d: j& |4 K; s, V$ K
            int i = 0; // 滑动窗口起始位置
    1 M9 t! E0 _* G% e        int subLength = 0; // 滑动窗口的长度+ X( K7 P2 F* A  D  s
            for (int j = 0; j < nums.size(); j++) {: S2 [# |% l! A) @
                sum += nums[j];( l; {5 M$ |) f" w
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
    & |+ [. n! t6 j: k6 \0 C            while (sum >= s) {& \$ \, ?+ k2 ]2 Z: U2 ?# u
                    subLength = (j - i + 1); // 取子序列的长度' c! |- H8 h; g$ t* @2 r- r
                    result = result < subLength ? result : subLength;//一定会赋值
    3 y! Q8 n/ f7 J6 W9 b                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    7 p) y" X$ K* S. U3 a            }6 k" f" U% w. I' f: z$ m2 _
            }
    % N/ \1 c% V- x0 [0 h( [4 p8 s        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    5 ~0 j% V+ N2 e- B1 M        return result == INT32_MAX ? 0 : result;& Z  [& k  A7 E6 t5 d2 x
        }
    , x6 A# f# N0 I( X! b};
    2 n" m6 o# W0 Z4 o+ _$ W1 A" t* j, h) [
    一旦大于,就减去左区间的值
    ) A( q" L: V, G3 L2 G- f
    % a+ [3 M/ _, R8 |5.最难题螺旋矩阵||) R. \: O( _9 x' ?' j- ^3 ^  `; x
    模拟顺时针画矩阵的过程:
    4 c$ T0 X8 a7 Q" Q9 K  C0 m( ^  q; X& }/ ^; m& o$ A7 P, Q
    填充上行从左到右
    4 c. e3 W, ]5 a8 Z/ \' ]填充右列从上到下
    $ A5 w& H; z& T( e4 V' k6 x; ?填充下行从右到左
    $ e9 @0 x7 x/ Q  J, l3 _4 ?& s填充左列从下到上
      }% y% m$ ?' ~由外向内一圈一圈这么画下去。
    ) J4 p0 A* X' ^4 I3 ~0 s* x2 E5 o1 X- z$ q5 {
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    + ], u: p" H  h' Z8 u
    3 L  z, \- K/ P& M. y
      x' {* M/ d. r4 m2 ~2 j; E! C+ X$ Y) G6 t6 N

    $ t" b3 s/ ^, P* n  F0 U# |7 R7 l# p$ h3 c9 Y4 c
    class Solution {
    1 i' o: |8 o* H# F' l) Hpublic:
    5 w! B2 z8 s5 y2 V: |& K; v    vector<vector<int>> generateMatrix(int n) {
    5 a+ {3 ]3 Q4 ^        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    7 [/ D4 E; w% z4 E        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置+ O8 D5 [4 I/ |& ~# r" U4 I
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理) w; ^  G) {! v( k4 H7 c' e
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    - _8 q% V, p5 i8 N* E1 M        int count = 1; // 用来给矩阵中每一个空格赋值: p' {8 M; I4 L6 `9 ~4 ?) R! `/ e
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    7 ~6 n5 {1 P7 B) S1 z3 b% m6 i        int i,j;
    ( N( r+ k" R! w        while (loop --) {
    8 G) O3 S6 o" \+ k5 F            i = startx;
    + @: L$ b  ?# [            j = starty;# J7 ?! a7 e8 x
    5 B  {/ _6 L1 d0 l) x
                // 下面开始的四个for就是模拟转了一圈0 s5 y5 i3 B8 U! u) }5 e9 j+ n# I
                // 模拟填充上行从左到右(左闭右开)+ ?' }: Y4 Z$ W9 o' T8 Q; ?* C
                for (j = starty; j < n - offset; j++) {
    ( L2 R5 H' ]2 s0 l" H* T                res[startx][j] = count++;" S, t$ r) T& W" X
                }! I# X" D/ E+ q. K( k
                // 模拟填充右列从上到下(左闭右开)3 m5 h/ x# B5 a- E' ]) _
                for (i = startx; i < n - offset; i++) {
    , P3 \+ a. L& c% J/ i. B                res[j] = count++;
    , f) ~7 U) b$ S8 J9 x            }: f4 j" K2 E( p. Y. J
                // 模拟填充下行从右到左(左闭右开)! b" `7 D' q) D7 ]
                for (; j > starty; j--) {$ m" y+ w2 T$ x# k* D
                    res[j] = count++;
    5 n+ l# r7 p/ T; B( M            }5 {( o2 ], z# x$ H* u" o
                // 模拟填充左列从下到上(左闭右开)
    2 s' a/ Z/ Z8 ~9 B            for (; i > startx; i--) {
    0 H3 I( T1 M' Q8 d  {* A; P, I                res[j] = count++;
    # d# t9 L  W' @: N( b            }# @$ _# }6 Q/ ^
    9 A+ j: ~' L1 Z: {
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)) T# @* D4 N) X7 d, ?
                startx++;
    7 u9 `2 V/ j( Q6 C( S8 @            starty++;! \; L# j0 t; e! ^' d( z3 F

    : i' ^* O8 k  H* O            // offset 控制每一圈里每一条边遍历的长度
    5 J, a% U# p8 b: p1 p. u            offset += 1;
    / T- x5 T) Q/ }, V! f4 d8 Z. l        }& ~, M( V4 A! t  Z. w' p, x. H8 h
    , V* N9 g' O0 ]% W9 X8 M0 ~
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    + w) n' ~) H. T, ]+ r0 s: s: O        if (n % 2) {
    # ^+ `' v, ?7 y            res[mid][mid] = count;; W7 b$ b# T) i$ d
            }; j' j# k, l  P! R
            return res;
    + z7 i* h# w" G) ^$ b    }
    / i$ s9 a* m% v8 |  q+ J9 \};' K) Q' z# f$ q

    / s. U- c) @( ^; P) Z' A' M) o$ `————————————————
    - L, ^+ n. C/ `+ E1 F# i版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    # M- G+ a- F- a- W. _5 `原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    2 I) ^( q' A+ X% z# M5 i  Y
    # `+ ?9 |' B0 r: P" x5 ~
    5 @3 E5 }% c+ a8 V9 ?' w! c* D
    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-7-29 04:56 , Processed in 0.429156 second(s), 51 queries .

    回顶部