QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1990|回复: 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 a  W% S/ ^. I; _2 c0 O2 }9 b. Q. f8 H1.leetcode704
    1 ]6 d* N. Z. P' h+ S% q给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。3 [+ Q5 _* R0 g9 ?* X) O

    3 a& j' `6 U, k) N9 B- [题解:升序 数组2 N* W, A' P5 T2 X0 Z

    ( ?7 X( V8 C( |7 _方法:   二分法. V) g+ L# t3 J9 f7 u2 {  Z. J

    ) i# G) \. ^7 f: x2 C9 D4 `$ b思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2). i+ U* w4 ~4 r7 I

    ; i7 _+ P: |2 ]+ v3 Q比较nums[mid]和target的值:
    ; o( n" ~$ h5 t& `6 [6 u5 h. A9 a. T
    如果nums=target,则下标i即为要寻找的下标;8 X' D7 a# K8 F( f3 ~, k, V

    ; |) V; q! V" h& L# [& b/ l" Z+ B如果nums[列]> target,则target 只可能在下标i的左侧;
    / S) h' K/ y& j2 r' E4 h) B
    ' U2 D, v- D6 s" T( b: fclass Solution {# P4 z. G6 ?( D' T" |
    public:7 ~/ ]5 Y8 l! `5 J8 W
        int search(vector<int>& nums, int target) {0 V) M* |/ M7 Q, j1 J0 q5 K
            //区间[left rigth]
    $ @& I& P, v& j        int left=0;
    ' w* |& s: B6 j. M        int right=nums.size()-1;5 f- O( z7 C/ R- H
            //结束条件 left>rigth7 D6 A6 Q" ^& a5 `( G6 r# e* @& S
            while(left<=right)
    * B; M  Y' J) B0 A+ G. O6 u        {
    3 O  F+ T7 ?; N            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]  a# S$ V$ _* b- `* |5 |
                //[middle+1 right]
    ( X! M' q! d/ F            if(nums[middle]<target)# r# Q2 u7 R4 @* }
                {) b& B2 k/ B0 p0 t; n2 h
                    left=middle+1;
    7 V5 G: P$ [' a+ \6 e            }9 J9 w2 \( i' v+ F8 \) i
                //[left middle-1]  C1 L7 G; r) s
                else if(nums[middle]>target): K3 B' H  u8 x6 B0 w" w* h
                {
    8 Q6 r; m8 O% f# }2 E                right=middle-1;
    + q% l6 C; R$ Z            }- s' N- A/ ^1 Y; j
                else{
    ! ~; J0 g+ R: D/ ^: ^1 \                return middle;
      ]" q' K0 g) w0 s- _+ R4 n            }5 x! ?( ?( |6 \% {4 g: @* t
    4 c2 |+ b& h2 H8 X8 `/ E  y! _) w
            }
    & q! E' H/ R2 `0 L; F& S        return -1;# F+ ^8 }. A! C* M
    % R6 u# W9 r- X/ z
        }
    ; C1 c: k+ ~0 z: t6 b! p};$ m/ @- v; O* M1 P
    1 Y9 p& C' y: n5 A3 b2 Q9 Z. R
    注意:; U* q, h% n% F# s# C9 u* U
    1 w/ v8 C2 L. X3 k$ P1 H
    (1)设立区间为[left, right],终止条件为left>rigth
    + ^& o1 u4 ]% E) B, f  (2)   (left + right)/2==int middle = left + ((right - left) / 2)9 `& z9 x' w& b, ^" W0 m( k
      (3)    通过改变区间的左右值;复杂度logn
    7 T* m  l4 @# F0 s3 [5 E0 x  W( t, q+ g5 O
    2.leetcode 27移除元素6 }9 \# f/ m7 D. ~7 E
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。: x+ z1 ]/ c! `' Z5 H

    5 k- ~6 P# N2 }) o# n不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    ! B8 {4 B* ?: M# P; S! J1 E2 B2 I6 R+ }. y! d4 A
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    & \) R! w7 K. S0 i
    & l0 g. n/ i1 k' H0 I1 `6 w, p示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    5 ]" ?, y1 ?3 b6 ]0 G
    ' [3 g5 ^- ^9 Q4 V示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。" ?6 o: C4 q" `

    2 C* y# n( p* k  H. T- n* _思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    7 T) d4 [3 E' z: w" [& g. b  i" W: G: ?
    方法:双指针
    + n) u6 _" ~+ H/ I: {/ r7 H9 o
    8 S# U$ {7 Q" H7 H& `class Solution {# ]( x/ R! q! [
    public:$ T$ T/ w+ I8 V/ _6 l) ~" a7 e" w
        int removeElement(vector<int>& nums, int val) {
    , ^, }* ^$ f) {3 l" n* a$ O& B% T           int solwIndex=0;
    9 D# {0 o( X" q9 }' O           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    3 w) `: T& ^; r5 L2 p3 C! Z% ]7 }3 c           {
    & F" j9 R7 Z" m& x2 y               if(nums[fastIndex]!=val)
    1 r+ n: v6 b& F               {- @" Z+ x& M2 ?) Y+ N
                       nums[solwIndex++]=nums[fastIndex];
    0 C1 I: t. R+ Q1 w: l9 F& d               }( D3 w) b3 V7 ]) j* Y, h3 `
               }
    ' f" a1 N  t, J- Z: V3 e$ O6 r           return solwIndex;
    ! V9 X1 |6 s% h. s; f" Y0 G% F    }
    , n- `8 D8 [9 H/ h( C% |( [};
    ' [. S% a8 R: Xsolwindex:用来覆盖
    ) k; n, _  h# Z$ O% t3 X
    * G( V! `8 O' R* jfastindex:来找删除元素++  l# p" B0 _& l* Q
    ! h1 M: h" u: \
    3.有序数组的平方
    4 S$ \' c9 S& `# y, C: ]给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    . z9 J: \% Z- H6 y( e7 |/ J" F: I+ o- ]5 r
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。! s. K$ |' T2 F0 x8 z

    , Q: c, q5 C2 D- r% R) O& G7 A9 _# W那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    3 D! B7 @4 i. o$ O& ]( j/ i6 \' M0 P3 c4 t1 \* e0 \7 e3 [
    此时可以考虑双指针法了,+ q: {; @+ z) M$ M: i
      [6 O( {3 J: B; V# a
    i指向起始位置(负数),j指向终止位置(正数)。
    + j0 q) Y) a. e; `) _. G! x2 R# e2 V! e
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    ' m( ?; l4 i2 u; n# k1 |7 a$ q' k* @$ C0 A
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。9 _1 p, t' b; Z# }5 }, j/ w" x
    1 a( }' S* Z8 \
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    4 @3 A* G2 f$ a; b5 Y# S9 ^, h/ h+ O* H9 V7 {
    class Solution {
    7 T0 T  `6 l0 z8 rpublic:4 }3 n# v  v; B7 ?# @; B  }2 V
        vector<int> sortedSquares(vector<int>& A) {
    : Y) p- \9 k1 s" d3 m$ ?        int k=A.size()-1;0 F8 ^- @1 s: t3 _3 F
            vector<int> result(A.size(),0);7 M; v* J) I6 ]6 D+ w% R% h: c1 e
            for(int i=0,j=A.size()-1;i<=j;), H( B2 K; G- Z0 z
            {9 J8 T3 y: [2 d7 Z1 q6 i
                //遍历一遍
    + G! r2 t% D  v, \, t# }, j- r$ Y8 T            if(A*A<A[j]*A[j])
    + |0 n6 K- f+ n, a' ?5 c+ ~            {
    , w; L$ b2 M$ b9 `2 _7 j3 E+ B                result[k--]=A[j]*A[j];  }+ X0 M, h1 ~# F
                    j--;
    ! b6 X- V+ |3 A  B7 n            }8 y+ {+ [# i4 u5 j
                else; R" u, Q) R. l8 S+ I
                {% \* [( B, V- G/ V5 H
                    result[k--]=A*A;
    + |& B/ L& Q6 K* m( ~- |/ h                i++;
    + J7 l; t6 P) S7 V6 _5 P) N  ~& [            }
    % c- y/ k; U4 m+ Q" T        }
    4 G0 Q/ V8 [+ d- x        return result;
    : i% h' Q7 z5 R+ z  k, K% _
    7 d  O' {0 t+ [7 I$ ?    }  Y6 s4 `& _) W3 I& [6 ~
    };
    1 F! g6 x6 i- o
    3 K/ u- N& O' L# Q4.长度最小的子数组
    : i1 c; C- K1 j9 u8 |给定一个含有 n 个正整数的数组和一个正整数 target 。6 M  U. [: `/ q
    ! E6 z7 f% X! _" J: i
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。. S2 Y( x" R( T: y9 T
    ' o# G5 i7 n8 i6 u
    方法:滑动窗口法
    / a2 E9 b$ i. x" U8 l6 x  d6 Z5 V: [6 k* v
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。; G3 s1 J4 C% `  o
    5 X7 {: |! [% O* Q' Q) B( E
    三点重要:: G% m3 R# q6 D# z9 S
    ) y: K1 M0 d' t& N) ?9 \! P2 H
    窗口内是什么?/ y# S: V) f2 v& V; B5 a; J# r: S* O
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    * w+ N+ L0 A) B如何移动窗口的起始位置?' \: n' @# ^8 K9 y; [8 c
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    + a3 s1 u5 c+ |1 W9 o如何移动窗口的结束位置?
    , s& {1 F2 K* \) Y3 G6 @8 Z2 D窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。) u7 o/ S# j: |# `

    ' D, K* j9 x- w 代码如下
    . ~( \/ a- l! _  P( K
    - s9 U2 l. R3 l: ^' b% \class Solution {
    ( o& N( G9 {# |3 K$ Upublic:
    % A6 A- T9 f3 \# j+ z    int minSubArrayLen(int s, vector<int>& nums) {; V) Q; B& Q  X. N: V* n2 M
            int result = INT32_MAX;  i) m' Y$ j' C' e/ C( q
            int sum = 0; // 滑动窗口数值之和
    4 _' M$ T& S5 e  Y; q# m# _$ H        int i = 0; // 滑动窗口起始位置
    9 U! K2 F% x- E" x- w# x% Z        int subLength = 0; // 滑动窗口的长度
    ; h2 z- O, e# ]: f' s        for (int j = 0; j < nums.size(); j++) {. z% Q$ S% A9 ?! Z1 S
                sum += nums[j];
    9 m3 V. n) k! `' E            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件6 ^  d5 H1 b% B/ P/ T
                while (sum >= s) {
    : T8 x& Q& G0 w& {+ y                subLength = (j - i + 1); // 取子序列的长度5 k: i$ g* h, \$ ~: G. t
                    result = result < subLength ? result : subLength;//一定会赋值8 z9 O1 M" ?8 L, Y! R
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)- f# O( }6 d' U" f7 _4 C0 O
                }
    ) v2 s  Z, j) J) S% z: s- i2 e        }
    * H9 o5 t0 k* }% w6 ?: |        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列( k; f/ s( t# b7 Z, _
            return result == INT32_MAX ? 0 : result;
    & p( J8 p- m% v6 ?5 v    }
    ' J' D0 o  g0 W};
    4 W/ x2 m7 y* S
    + p  f* ]" s" q4 g% G/ f9 F5 P$ ?# F一旦大于,就减去左区间的值
    0 I: k" o" d' d4 A, I; a4 P& D/ B
    5.最难题螺旋矩阵||" I9 n$ d8 m" _% Y' g9 ]
    模拟顺时针画矩阵的过程:
    , |4 i) m$ L8 |6 e$ J
    6 @( t4 T" q* k1 g( k- p' I填充上行从左到右
    ' s% d3 }/ [9 d+ |" S填充右列从上到下
    3 R8 W+ M4 Q" V3 ~$ B/ y! k填充下行从右到左
    % P' g$ c- ^" T. ]* N% r9 B" }9 S填充左列从下到上! ~* B/ m/ x* d* v. q
    由外向内一圈一圈这么画下去。: h, j2 g: r. s8 U+ x# P3 C

    ! a7 h( G2 O, u& [- v: e这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    $ u3 W& y3 P: d& ^/ t0 a: n' X9 e( O% X+ f' P

    - @, O7 l( w3 w4 D
    - K0 K% \) Z: j5 B, @* Z
    & _- H+ a. x  k
    8 t) n( ~/ v  a! o. z$ Lclass Solution {
    / Y+ m4 ?& K$ L+ [public:
    + z/ S5 {5 q: f2 P, \' A# e7 V. U    vector<vector<int>> generateMatrix(int n) {9 ^, A, A# c4 t4 U/ v
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    . e. i/ d# n& O        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置9 L5 @- x5 L8 b. {/ d
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    2 \) p" R) |6 Q2 H3 o& E$ e        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)* B/ Q7 b9 i3 A. A
            int count = 1; // 用来给矩阵中每一个空格赋值
    - o( b$ e, B  b1 k0 G; n5 _        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    3 f! m) J1 ~, Q5 r; ]+ [( p& @* F& U% |        int i,j;" S* y; p: R4 J/ q/ O/ ~9 q
            while (loop --) {( M# n- |+ C8 s/ Y1 U1 F
                i = startx;. N+ `, x7 T, F+ y3 q
                j = starty;
    ; w- c' U- Y, `( f  F4 }2 G; z0 q1 \
    + i0 b; \2 o8 |, A            // 下面开始的四个for就是模拟转了一圈
    . y/ N7 Y0 T0 v4 I6 V1 c            // 模拟填充上行从左到右(左闭右开)
    " E7 c% j, N4 Q* U6 ?/ E            for (j = starty; j < n - offset; j++) {
    & H6 D& E9 K  l& c                res[startx][j] = count++;, N1 O: k. c$ W
                }
    + Y# m. m3 H2 b! W- M* v6 F9 r            // 模拟填充右列从上到下(左闭右开)0 C1 m0 @, a+ K% _( y
                for (i = startx; i < n - offset; i++) {' i6 u0 U" ]& @; q) J5 f: C
                    res[j] = count++;9 Z9 g# u; {: O' u
                }
    / t+ B# k! t8 ^; R4 X6 ^* ?            // 模拟填充下行从右到左(左闭右开)% ]; s; ~* A, J6 d2 H# r2 r2 P
                for (; j > starty; j--) {7 ~% {" v- S1 N3 Y0 w( I2 _
                    res[j] = count++;
    4 l2 z0 Z  @3 l! G0 N            }+ B+ `* Y, _/ ~- q
                // 模拟填充左列从下到上(左闭右开)% b  o+ V7 W: B+ q5 v* `, p
                for (; i > startx; i--) {6 o) o) u9 y# r: E) a- y1 d
                    res[j] = count++;
    ; s3 ]- @3 L8 {/ N. E* C( i            }1 Y; d4 N, R) x/ E+ |  N( b
    # s) b4 e5 T: Q  O3 f
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)0 c, X/ L" l9 e5 [6 _5 E
                startx++;. b( X" d; H5 a' a
                starty++;
    " C. r; M( t# R/ R& b0 K1 Y' i% y7 X5 F" {* |+ `
                // offset 控制每一圈里每一条边遍历的长度
    . g5 C# [! u. L4 B9 T) Z* C3 C% f# s            offset += 1;
    ) y% e' c; c, u' L2 q        }2 E( W) g" v$ t7 c6 |* p
    : P5 }; G" o, W7 S4 X
            // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值5 a) K7 G6 K8 @: w) S
            if (n % 2) {
    * O6 F! |+ L6 F& s- |. m            res[mid][mid] = count;- i" _+ u" x/ R, V& ?) ~
            }7 x& a; Q: ^9 V: i" O' X4 Q$ M
            return res;1 F# X* ^; j5 X7 T. o
        }1 p/ T5 P5 i7 e/ q; C$ P. u( r  h
    };
    ! @3 }8 x& }2 p( y
    / X5 z& s! g( V: U5 l+ R- `————————————————
    4 ^% I- y8 c9 I版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, W5 }) a# e' [0 Y0 i
    原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
      s0 o& {% Z& T7 ^; i! H0 }* F. N8 [- y' r8 Z5 ^9 S+ Y" v  }, Y
    # w+ ~3 u9 o/ |) ^
    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-4-12 07:42 , Processed in 0.401918 second(s), 51 queries .

    回顶部