QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2035|回复: 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
    数据结构之数组练习. ^( f7 J3 v2 b3 f* Q, d6 R
    1.leetcode704
    / A( y0 j% ]2 w' }) C; j7 s6 v给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。$ }. c7 t  D  a% @: V

    ( R6 \  G$ e! \% \* Q# s0 S- F题解:升序 数组
    ' i# X! M- b- \0 |8 s7 `0 W' j6 E. p# i( Y, {- I/ e
    方法:   二分法
    0 K8 g; V$ |4 O8 j/ r2 x
    5 P& K5 A8 T. S0 h6 G1 w思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    * \4 W5 V- U& _1 v3 U' z% j3 R7 ~% w  g. ^6 q7 x) U8 z& K: U! g
    比较nums[mid]和target的值:
    # |7 ^, x& Y* ~' U  k; w7 V# @2 H* j
    . `! {$ f# B( r2 O  T如果nums=target,则下标i即为要寻找的下标;
    * X# ~0 S& s" f5 J$ I# v
    $ D& F5 C4 P3 g9 @2 c/ f" m) u8 m如果nums[列]> target,则target 只可能在下标i的左侧;
    , a% P, C1 p  j2 x2 t% u2 H
    1 V0 A- D! V5 V' U+ }' jclass Solution {: m& B3 b/ p6 x& K5 C
    public:
    4 x! Z; _3 R7 E! `* ?& t    int search(vector<int>& nums, int target) {
    3 h1 P, f; j( s+ e0 z1 i0 \+ {8 I        //区间[left rigth]; [2 @4 [, c; K2 A' r& C2 @
            int left=0;
    4 ?; h0 ]6 f6 e1 q1 U        int right=nums.size()-1;7 {2 H1 Y) o* G( T7 _$ N
            //结束条件 left>rigth
    ; \) u' h6 h9 z) ~: N6 W0 `7 f        while(left<=right)
      A- P5 {% ]0 N5 K/ k4 f        {+ f& _. b4 y: a/ V: ?" ]
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]* L) R$ j3 M" o) ~7 {% L( J& c  E
                //[middle+1 right]' O2 {- Z. u2 Q; i
                if(nums[middle]<target)
    : v5 D6 E& m$ W! \, z: }* S  x            {
    6 h; C9 _/ A2 K# N: X7 t                left=middle+1;
    7 B2 I* E3 G: L; q            }
    / m# t- v* n( j7 w# f5 z            //[left middle-1]
    $ w4 N% ?% y: H8 u' o* t8 Q9 q            else if(nums[middle]>target)
    6 s( q/ G# _# Y2 D3 e9 t  a            {8 o# [0 F. Q* ]2 P: R( Y1 w
                    right=middle-1;/ h2 ]% S3 Q6 q- ]
                }0 \% |. Q# N# u" ?
                else{/ {. I! {! w4 C8 m+ N+ f; j& A
                    return middle;
    4 E* L- [, ]' d# ]8 T            }4 ~0 t0 O7 q6 [0 d9 }# T

    % H& Q4 i* B1 u/ ^8 F  ?        }
    ( W/ \0 S/ y5 W2 t/ t" L5 m* e        return -1;
    4 W$ H' C) l" @; c, }& A1 F7 D8 O% G5 g0 @: z4 U: A
        }
    : P% g# D4 T8 t: K& i};
    * N( }1 w' U: Z
    ! ^9 m# b& x$ b' A0 s2 W注意:
      s1 y3 i9 d+ T$ ~+ M& ]1 c$ y
    + M3 [- Q  b: p4 }(1)设立区间为[left, right],终止条件为left>rigth
    9 ]# ?5 b; }* i: b6 n: a  (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    ' A5 R, x" m. M( Q3 Y, p  (3)    通过改变区间的左右值;复杂度logn
    % a& O2 u/ H- a8 D) F" a
    7 C- X. }9 C) v' Q& A4 j2.leetcode 27移除元素
    " v2 o1 ~+ z) w! K5 U: o; [3 N给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    & n/ J6 n% J) x- e, m+ T& M
    & |& L2 e/ `; I  @不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。0 x7 e6 k' D) i3 A& g5 g" V! f1 P
    2 \! I2 }0 y; T$ U4 s7 q$ x2 [( G
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。% O- L! |$ N% }- e7 V' e

    ; F: r: r) @) X' B& ?4 X示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    $ M) F. I0 v. H" k0 ]+ T4 o7 |3 Z# o, A2 B
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    " k+ m7 H: g; I5 o+ i
    0 m/ s% N; B) m- g, s+ f思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。- S) e% h5 y+ o2 k" k( V
    4 y9 E) Y3 Q" I; ~
    方法:双指针  R* [/ S2 U9 X/ ^& I- x

    6 u' L1 [4 L$ U% n4 g4 J: Jclass Solution {
    3 x4 ?- s5 l) |: \* f) mpublic:, F1 ?) s1 {3 o8 {0 q( W: d- I# l
        int removeElement(vector<int>& nums, int val) {
    9 m  q) l' k, d  ~2 \0 @           int solwIndex=0;6 N, f$ q* d7 ?, Y
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)* @8 X2 H5 I6 `! w
               {0 v4 q; ]; @" o5 ~
                   if(nums[fastIndex]!=val)
    4 u8 c9 u3 i. X5 @: {0 @$ P* Q               {
    ! O- _  z- q" J5 y/ M                   nums[solwIndex++]=nums[fastIndex];
    3 O3 I" v# d- }1 H( V               }9 W! l7 g4 u6 S2 u# ~3 e
               }
    ' s5 \; w4 s4 e8 w& T           return solwIndex;
    ) j0 _/ r% o- [8 |9 T    }
    % m6 ]# `8 W5 p7 y8 z/ a};- a) }* F- O0 t3 x8 _
    solwindex:用来覆盖  `$ e5 `3 x. r8 q  H
    * K- M& m7 K* O4 U
    fastindex:来找删除元素++
    % I% H1 y( n) d* r0 c( K' O# n& E
    # P* W+ R+ g/ R# u3 k/ J3.有序数组的平方- \  ^6 ^. ^' u9 N
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    & q: S0 \  ~9 G( ?+ N4 W& \, B$ U6 b& [
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    $ a- @8 O8 \/ {! e3 \5 j% N- k7 b  l0 h4 M& B
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    ( e# l# W4 k2 r# V7 C0 K% f$ P2 T# q2 ^* Z8 a
    此时可以考虑双指针法了,
    4 D. Q) @; |& i- \% @" W+ D* _
    + ^7 W  d5 _  n+ e7 R" {i指向起始位置(负数),j指向终止位置(正数)。8 q4 u! @( A) ], l1 ?
    + s+ E7 ]+ N1 Z% V; b
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    0 _$ `- X7 V6 R5 R! j, j0 @( Q# X, i) x+ n1 N" C" n* A
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ; @8 `& c  _7 q/ S: S6 H3 J7 T- ?& e% x6 Q; c% o3 {: A) [
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    % R7 F5 K) A# Q: I- R6 o' S
    ! |$ V# _* B% Oclass Solution {
    - q5 H) |5 `) P, e+ Apublic:
    4 A- b* m3 F+ Z$ Z/ Z8 p    vector<int> sortedSquares(vector<int>& A) {
    ) N5 w2 h$ }& D$ C+ }# N        int k=A.size()-1;
    ' g: p! y8 t, i        vector<int> result(A.size(),0);/ j# m: k) j/ z& l
            for(int i=0,j=A.size()-1;i<=j;)
    9 U6 z6 k+ R; u8 {        {
    4 R$ A8 V( v* s; P% C- M4 S            //遍历一遍9 q1 H& E9 @1 E$ l. j; g
                if(A*A<A[j]*A[j])( j( b% L+ D6 s2 d
                {& o" D' p0 t5 l6 s% n; h" X
                    result[k--]=A[j]*A[j];
    ; f& |) D+ I9 P* z- P, W( X                j--;) E: k, x. Q- Y6 T
                }
    5 e: E% S0 [! y$ Q1 s            else) M4 C: I. ^) X' Q0 E
                {# l& F' F! U: B2 V  y6 [9 c
                    result[k--]=A*A;" v+ c6 a+ q; s4 {. [
                    i++;! C' `  m4 {# O& e6 u1 ]
                }+ s- l+ N# M& y* Y, M
            }$ a2 V( \4 B# H9 j  ]$ A6 L8 y
            return result;
    : K) [& b# t9 t2 z; B! P, O% i* s% H7 p- t) H+ I
        }
    6 k/ S* O  J5 W% z+ @* m) T3 {};
    & @2 |& j2 I+ J( ~  Y8 \+ q: G" Y! t% k1 D+ U- u0 e8 a9 S; k
    4.长度最小的子数组
    ! c1 P% M' f- T5 [4 T2 l给定一个含有 n 个正整数的数组和一个正整数 target 。
    , x" g$ A3 G1 j6 V  N* y9 g0 U5 G
    7 v2 y. D2 r. J# e4 p/ `找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
    / q. ^# c( ^( X9 A) [6 k5 O' b4 G2 K5 x5 l# T. S" B0 d
    方法:滑动窗口法6 v9 W; J% F% J6 B
    ! P5 S/ r1 w6 g. x& o3 O
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    0 R6 j+ Y8 S5 E- k- V
    . {- ~- F! L9 ^6 e三点重要:
    4 M) @, ?8 ^# g0 Y: J, ^5 ?& T. l. m7 W0 S0 ]2 ]' @
    窗口内是什么?
    6 [: O  e; T$ X+ L窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。7 P$ f4 l4 i5 P, U- g, p! g1 m
    如何移动窗口的起始位置?. {1 B# Y. ~8 _- Q5 |
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    8 v* A5 i& t5 _# N1 }1 y3 P3 Z* m如何移动窗口的结束位置?* K) e& y$ V2 D/ r- R
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    - g9 b: }' b  \, T+ Y- o: `$ L# J- k6 T7 j! p. X7 O
    代码如下# c6 u/ B1 ]% f5 k

    2 |( v8 j' ?5 \! |" ]class Solution {7 z* p( ]: t1 Z& B4 x  p) ]! X
    public:
    ; C% J0 A5 _% K/ U6 Y4 ]1 I    int minSubArrayLen(int s, vector<int>& nums) {
    2 U, P7 H, ?, R3 M/ V8 Z        int result = INT32_MAX;" B8 |- b& g+ q) l" E( g
            int sum = 0; // 滑动窗口数值之和
    5 x5 @& _. C, ~1 R) `        int i = 0; // 滑动窗口起始位置
    , |( \% x# r) y+ ~- l( X9 n        int subLength = 0; // 滑动窗口的长度% l" g3 J; V& F
            for (int j = 0; j < nums.size(); j++) {. P* Y; [, p8 {$ }  h
                sum += nums[j];
    3 [) P! a% K  p% q+ U            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件1 F0 ]& \- l* |- H
                while (sum >= s) {; K7 R1 }( W, O$ E! Y
                    subLength = (j - i + 1); // 取子序列的长度
    8 o, |  a; [" |$ |! q; R                result = result < subLength ? result : subLength;//一定会赋值5 \5 D" j( ^* v, u# I
                    sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    3 f& J! E6 D5 t            }
    # O! b7 b. L0 s3 {        }% @4 `2 P" q2 R! S3 s# _' v# V- Z
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列/ D5 S7 l% ~/ U  J( f! v
            return result == INT32_MAX ? 0 : result;
    7 o. B( x$ _+ X) p! J' E- L* _( F    }
    * y! s$ Q8 b9 r4 K5 k/ E};
    1 I4 T& S6 _' t) R5 Y' R8 A; t* s5 S+ {/ ^4 N
    一旦大于,就减去左区间的值) i2 ~+ T* h: H: ]- M
    , [' z7 u9 u  L# l6 a3 H
    5.最难题螺旋矩阵||. u8 f& k4 b& g$ F
    模拟顺时针画矩阵的过程:6 I* |; Q8 _5 T9 ^
    7 u9 c9 {% i; q& r; \9 y8 K" S: B
    填充上行从左到右5 a' ]" e9 K- s
    填充右列从上到下. b( j1 e5 y. Y% I0 C' d
    填充下行从右到左
    ; q0 u3 X3 N5 g填充左列从下到上1 ], L4 V7 t8 X! D* k
    由外向内一圈一圈这么画下去。# b& {4 w  H5 _' @% q

    9 Q7 H$ L* S$ \5 i: Z' C这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。" I$ [  ~& o& e% D8 F6 y$ M
    4 Z6 T) B! o  b1 C$ v7 K( O

    7 r2 L7 |. C) y4 S* f9 x4 A
    / m1 O9 B& b) @* z$ [6 Z4 ^# ^3 Q: X! k) g9 o2 r6 b4 g; j
    4 B0 \2 y- x: ^7 {- x0 Q% E+ d
    class Solution {: C& @3 |) G0 Z' z/ N; K# p2 C) Z
    public:( s/ `. V" d6 N3 ?
        vector<vector<int>> generateMatrix(int n) {" r/ j$ Q& q& s5 ]0 ~- |* o* _
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组  o8 ~1 a+ N" j( F
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置1 Z8 X5 h; |& q
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理1 a1 L& |3 ?5 J/ s, c6 c
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    3 `& C; j3 n8 F3 o4 z9 `        int count = 1; // 用来给矩阵中每一个空格赋值
    , c, r' ?8 P; w& o" x        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位& x9 N! h. Z( B( z! p
            int i,j;
    9 k% j0 X7 ?4 g* s        while (loop --) {
    / x# h3 R: i: n9 R$ q8 a0 ?            i = startx;0 v" T( }8 Z- M* X
                j = starty;
    , u$ e; V! {/ g2 h( d! o* c) n- H& \1 G# v* |6 z6 J: }
                // 下面开始的四个for就是模拟转了一圈0 g" `2 `$ z- Q$ i
                // 模拟填充上行从左到右(左闭右开)2 R+ F5 m$ C2 I1 {, ~
                for (j = starty; j < n - offset; j++) {% |& R% T) w9 `4 F) W  N5 W
                    res[startx][j] = count++;
    # J8 y0 z0 D- ^) `            }
    $ e' C8 O0 j0 n            // 模拟填充右列从上到下(左闭右开)
    " \2 H# ~% f# H2 H/ w2 A5 p            for (i = startx; i < n - offset; i++) {, K& e- Q6 d7 ~- D8 }: P! i3 R
                    res[j] = count++;9 h! c5 J8 K6 A, x2 L& X$ D0 D- |
                }, x8 A6 I" O3 a
                // 模拟填充下行从右到左(左闭右开)! g" x9 A" j5 l% S5 S; C
                for (; j > starty; j--) {" a8 {1 A4 h+ }7 f$ s, f
                    res[j] = count++;9 j  k+ W6 P$ K4 k. Q' I
                }* H5 s2 h' E' A( E4 y; c5 D0 V
                // 模拟填充左列从下到上(左闭右开)" v: o: B  K- x! e( S4 i9 e# [. P5 J
                for (; i > startx; i--) {
    % B6 l( T9 s6 a! H$ A0 C, ?                res[j] = count++;1 k' {/ `% _, P! h8 a) ]0 ?
                }; {6 V% r0 k9 y0 {
      c9 e8 V; l/ b1 a0 [
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    $ I2 I# k, P3 g            startx++;
    " V: O* U7 x6 M            starty++;: o( k( k: Q6 P

    , {4 s: J1 m) [7 b* d) K            // offset 控制每一圈里每一条边遍历的长度* t& x4 b, |# s$ F8 F
                offset += 1;
    # X' s. T0 X  J0 u( o+ G        }
    , c" e: V" M  I
    & @7 f4 K5 z7 Q        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值4 \  Z0 P( p% c% x
            if (n % 2) {
    ) q3 s# c; u, U& s            res[mid][mid] = count;! j5 M% w- E! W) r3 o
            }
    + I" H4 g1 R- h        return res;3 K% M' H7 S1 W4 f# D& }- u
        }5 c  ?. i/ [* N
    };
    9 A+ v2 Q! t0 s/ @2 c- Q" _$ G  E4 M
    ————————————————
    / _6 ^0 j) T3 T版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    / M( n; G9 ~- S' R原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    + l( U8 @3 L, _$ _( l! j' P
    # ~9 I7 G& P& S' s( ?! N1 K) h: o6 Q
    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-28 11:25 , Processed in 0.372426 second(s), 51 queries .

    回顶部