QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1987|回复: 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
    数据结构之数组练习
    ' M1 j4 O; q5 [3 F3 C1.leetcode704* S. t* R4 K8 P7 f
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
    6 t  I4 r  G  e7 t5 g- B. z) W' h( g6 p9 J: f
    题解:升序 数组9 b8 a1 m7 w6 v( q! n; d" g
    % K6 p3 v0 y3 g# q5 J4 q  X! g7 ^
    方法:   二分法7 z2 |# `+ i, K* k. ~5 Z

    & H+ x' m8 ?, Z" Y思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    : N* ~: C. m; \$ K/ z5 L
    # r9 t1 w# C4 v" {. f比较nums[mid]和target的值:0 V( |) R9 Q0 O# v& A4 W

    + K: }  D3 E) e  t" H如果nums=target,则下标i即为要寻找的下标;
    ! e6 j: D& Q4 _* e, s+ M# s: t
    : }/ S& {+ n/ s6 R* W$ b如果nums[列]> target,则target 只可能在下标i的左侧;6 B( ]  Y7 n- S

    . E  ~) d; P4 v, ~class Solution {; m  ^  t6 m6 Z; l( k
    public:3 m: r8 j# i4 e' j) G- I1 m
        int search(vector<int>& nums, int target) {4 M' _' O& a& c! \# G2 q
            //区间[left rigth]$ m2 E% G5 e3 n5 O
            int left=0;
    0 n6 n, d6 K) A- G' O4 H2 ^4 C        int right=nums.size()-1;
    1 u+ ?2 T4 J8 u        //结束条件 left>rigth0 @0 |8 F4 j) Z# v- u( R6 e  U( B
            while(left<=right)
    5 z* L( N2 F  {4 e, @' \        {9 z' A8 x8 @" A6 \8 p
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]+ {7 g. X1 j! e' X
                //[middle+1 right]8 K5 r" T% y) A, I3 ~' L
                if(nums[middle]<target)
    ) z4 I2 d( D9 k- ^, ^( ^# e            {- H7 y5 Y0 Z4 V, P3 Z  T
                    left=middle+1;' ?7 W# j. T: e
                }
    ; K0 u8 G, l$ K) W/ N) A' i6 k  m' C            //[left middle-1]- e4 D; e. g, E) M$ F7 ~5 q2 w
                else if(nums[middle]>target)9 B5 M9 \; r* K! \5 b% l0 X5 d
                {
    9 G1 l* W" b& L+ W0 H  |/ D                right=middle-1;
    ! B3 k8 o% Y5 T( h& u            }; s0 V, F0 l, }/ F: t% J
                else{
    ( ^7 [: k5 @) t1 K0 t8 U# k                return middle;
    * ^* O* v# t8 v  n' Z$ `3 j            }4 t9 v8 V" G* f' N1 |

    * o6 K* b! U3 ]7 J/ m        }) U' k; v" J! z/ l9 _
            return -1;
    ) W, A' Y! V7 }, W0 o( r5 r' Z1 `% e* p) C; T' w2 d  l
        }# |! f- F6 _2 P/ R$ x6 d# @
    };$ k+ S% w- J0 `! E  v7 v* ]2 _
    # s5 I& y1 c5 N/ q
    注意:6 O; S$ }& Q: K2 r3 d7 L
    ; x* K1 f" W' j
    (1)设立区间为[left, right],终止条件为left>rigth# w2 m5 F3 ^2 d: f. |4 f; L1 q
      (2)   (left + right)/2==int middle = left + ((right - left) / 2). R  _# T$ ]! R" Q
      (3)    通过改变区间的左右值;复杂度logn
    ) M' h: P0 n) n% M. N- b: y) W6 E1 n0 l8 v' O9 i
    2.leetcode 27移除元素& p8 C& F# ]# x3 F# e3 i: |
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。# ~0 v) |  m: Y2 [; v5 Z* C; b# T
    + V0 ?" p) s/ f8 Q& q' Y
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    ' f( r+ J) O% P1 o6 ?6 g9 _; j
    ' U8 _% I1 o4 r, h- L: D  i元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。% T0 W) L6 v# p- s! H2 b- O9 U
    ! T/ H2 s. D1 W
    示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    3 ^& y  h! U) Q- `5 R( m
    ! G4 B  k; k* U1 t示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。1 T1 ?2 K$ G! J9 _6 D$ G
    . |# y  C( a9 q" x
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。0 z' R" N3 A/ b

      R" s) h" N0 c" B4 B# b$ X; L' d方法:双指针
    ( S9 ]2 i) S! C* s0 z; K8 N- p( `) w1 Z' L+ Y3 _
    class Solution {
    % w/ D% X! P* [# [( ypublic:: O  K7 e5 J1 ~0 N6 Q
        int removeElement(vector<int>& nums, int val) {: \% k5 G8 Y1 L8 a) d9 K: X
               int solwIndex=0;. K% }0 \  @5 g
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    : N1 P6 r' G' s. h3 n/ W           {
    0 |! S# l4 X( v( _" q               if(nums[fastIndex]!=val)
    ( g& \) g0 v; e5 S# E% ^               {
    - y) y8 H3 A* C9 B. E! J6 b3 V                   nums[solwIndex++]=nums[fastIndex];
    ; h% H; w# U" f% V: B% O               }, ~# z" I8 f) r/ P# }& E
               }# `  m9 `" c7 n2 @& N$ q
               return solwIndex;7 X+ A" R4 P- v3 Q/ @; s( c0 l
        }
    9 r+ G( E+ g: x1 H$ J" Y};; f% |3 E7 b/ i+ A8 p: |
    solwindex:用来覆盖
    0 d0 a) X. a  C2 c- U$ e5 Z8 q* l  i* E4 R- ]/ v3 O: l; J
    fastindex:来找删除元素++/ U7 [; Q* |2 x2 I, M9 a
    & p  T. ^3 k0 ]: X$ I& E( Y. S
    3.有序数组的平方4 L0 Y8 x) ^: u1 }/ p: F0 Z
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    ! ~% G! `& b7 q  @0 _/ W
    . W  i8 L4 [3 N8 g4 n' w数组其实是有序的, 只不过负数平方之后可能成为最大数了。, R- z. q$ `3 J' L5 o

    2 O  X! ?! Z5 |4 A( X( ]8 q那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。/ t1 c/ [5 l6 E6 e  A8 V% ?' M
    1 x4 n6 v' h$ M: J+ w9 |
    此时可以考虑双指针法了,
    8 A4 i; n, f( D* K3 V1 e" Z
    5 e% y! d( z! v1 N$ V9 h$ p1 y9 bi指向起始位置(负数),j指向终止位置(正数)。5 A  j. y7 X# X" r

    . v' L  ?$ O( _6 S" D* p定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。: e# X0 l; t( W! v4 p( z

    3 j2 ]" I: K2 q6 ?) T: z如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    - k# }6 c1 E' _3 ]) ~% m! F3 S% b$ E9 v
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    & t: p, W- u  y9 H: V7 i2 S: t: y) t! f- f# R, a, g( H
    class Solution {
    , M6 B  d# C. _0 ~3 Ppublic:& j% C1 m9 a# K1 G6 Q- S- u4 g
        vector<int> sortedSquares(vector<int>& A) {0 @1 @& n- E% [  M- G2 B
            int k=A.size()-1;
    : _) `9 j( b3 e% S) Y( g        vector<int> result(A.size(),0);
    8 \2 e; R: O: R0 a        for(int i=0,j=A.size()-1;i<=j;)/ h" w5 M+ W( H, ^3 X: _1 R
            {
    ( i, ^: o- {+ j% a            //遍历一遍
    7 G6 w* _; [4 e8 r; U% h            if(A*A<A[j]*A[j])+ ^- h( {8 a6 }; ]# q
                {
    . k# _+ l5 v4 {0 e3 D5 H                result[k--]=A[j]*A[j];
    % W4 ^! v# {- k( W7 u4 k  _4 M                j--;
      \, Q3 Y7 T+ G4 ^' G, b* @            }
    4 G* x3 |# F1 j( L            else% d& Z8 G) p4 {) l4 P
                {
    7 }: z  G) t& V! I* R                result[k--]=A*A;
    ' \) }3 ]. `# E/ I$ T) A% B                i++;6 v4 P$ P7 M( r0 u# D- P$ \
                }/ [( B' j; n' S, J& M
            }* B0 J( i" _4 A5 f  b
            return result;
    0 S# y, Z; d( @, ~' r% W6 P, J8 p5 H8 h
        }8 s! k$ _) D3 l* u% v/ b1 p4 d0 B
    };
    3 p1 A" }& Q1 \( k1 w8 Z) ]! q) \' e9 M0 c5 R' N# C
    4.长度最小的子数组& m, U: i$ i- G3 |
    给定一个含有 n 个正整数的数组和一个正整数 target 。; W* S) f+ T$ Z( C
    ; b5 y& x- i+ t6 O# a. b9 |
    找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。3 m1 \' h! e6 U- S8 O
    ! I: \; @  A/ K; |3 n( X
    方法:滑动窗口法' P8 V4 z. E8 I
    0 g4 v# u6 e) H/ d
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。" w+ P% G" T$ l# P0 S0 U
    ! g$ ]+ C! d( R$ ~6 L3 [; K
    三点重要:
    0 q9 Z* j2 M! }- Q1 _6 r
    0 L$ K3 {1 ]  E$ c窗口内是什么?
    4 O0 N& i% _( |窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    " q5 s$ f* }: l9 D$ A* f8 A如何移动窗口的起始位置?
    $ y" c8 f3 ^( F3 Z9 x4 I8 x窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了# |0 }& f9 S6 o* x$ U
    如何移动窗口的结束位置?4 y3 y1 h) i  E' ]" V' H; \/ ^
    窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。4 f! E  t% x# Z5 \4 U+ E2 |
    8 g0 Z& X' a7 o7 r" d3 u
    代码如下& S1 m8 a" E; y6 F# L
    # Q, O6 f( ?& F% u, e
    class Solution {& q" B% F% A4 Z& H. q, L' V8 ?
    public:
      G: `$ Q5 O1 E7 \    int minSubArrayLen(int s, vector<int>& nums) {5 r1 U" n4 j& ?5 {) m( W6 H
            int result = INT32_MAX;6 i' r& R6 ~7 C. V5 R% ?
            int sum = 0; // 滑动窗口数值之和
    # c2 e6 N" ^7 ^. i3 E; g        int i = 0; // 滑动窗口起始位置
    ) C8 s! M4 l' h; U6 y, ~$ q        int subLength = 0; // 滑动窗口的长度
    7 e5 N) e& T5 U: y( ]3 v        for (int j = 0; j < nums.size(); j++) {' X: F$ P1 X# h- g- d5 v
                sum += nums[j];
    ) [8 \% D. I  u            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件# K- C# v" I8 b& K
                while (sum >= s) {
    7 U1 R- ]4 h5 ?                subLength = (j - i + 1); // 取子序列的长度+ `2 Z' A) I; y
                    result = result < subLength ? result : subLength;//一定会赋值
    8 S7 o! q' @2 [4 _                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    + v/ h' d4 f1 E7 n* z! u! |3 B            }
    5 Y+ s: |7 q1 T% j1 t0 E* P        }
    % W& h/ }" ^' f$ D' J( [" B+ B        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    # Q9 O2 k' [- K9 w        return result == INT32_MAX ? 0 : result;8 C+ P1 ^! ^; d6 e7 h, H# l, v& Y
        }
      Z4 T8 A" |: |$ |4 s};
    . Q$ v: z7 |4 w3 e/ l2 {  l4 r3 d( _' T6 ~- n& E7 n
    一旦大于,就减去左区间的值
    4 M6 ?* X% f" [
    , n$ |) m; A5 v9 H* e5.最难题螺旋矩阵||( s5 Z. d! }% A: }
    模拟顺时针画矩阵的过程:  }7 w* i, U- R" d8 M8 p
    0 @) m; t* ~4 T' J" J* H  O3 \
    填充上行从左到右3 t; {, b7 i' ^8 j' `7 _
    填充右列从上到下" c3 V, k! c- k0 x1 A+ U
    填充下行从右到左
    1 m6 h. w' ~5 Z! v9 x# i填充左列从下到上8 f0 [9 ?2 f1 A
    由外向内一圈一圈这么画下去。. b/ p) c% v8 i8 x! b' t
    & @6 j6 B: G2 v% y8 e/ E
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。2 _) @! X' A, p! N+ M' L

    ) O1 C% p6 G! [$ f. n+ {0 X( _2 v: {9 M4 u7 E* l4 |+ U

    3 ?8 h7 t5 i, J; w$ l1 f
    * P5 I! W* A9 [8 I  U8 S/ F- \( ^+ v: d& V; Z
    class Solution {
    $ ~1 q, Z  o% zpublic:
    2 L( A6 z2 |- N. i9 h# t+ s9 g7 {4 y    vector<vector<int>> generateMatrix(int n) {. E* A* r* p* Y0 ~% C
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组1 F3 h( A6 A% T" [9 W. o8 a
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    ! U7 l1 T( J" @1 h        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    / Q: f/ d2 R  n& b0 E+ L' `' W        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2): w/ o3 q* C3 U$ }0 x2 N' C
            int count = 1; // 用来给矩阵中每一个空格赋值
    ' c' U2 I2 {  |: j1 S; J" _        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    , N  d2 w* n+ d" k1 b        int i,j;
    ! Z% j6 u+ [; [3 ]% N        while (loop --) {( p$ E" b  _' e6 i9 z; M2 b0 i$ T/ k
                i = startx;1 \, D) n0 f8 Z9 _- r* T  [
                j = starty;3 a  L/ @' _0 N& u$ E0 E. {9 B7 J
    9 s8 d5 M* ]' y" u. G- {* C
                // 下面开始的四个for就是模拟转了一圈# o" R% [* K5 X# \' N
                // 模拟填充上行从左到右(左闭右开)
    2 [- |2 s/ o, x7 D6 s            for (j = starty; j < n - offset; j++) {
    + p$ A% o+ }/ j; n% b                res[startx][j] = count++;
    ' [) U6 N4 m. V, o            }6 E3 ]3 g, ^* t2 k, v0 w# C) b( P3 n
                // 模拟填充右列从上到下(左闭右开)) A8 S) k7 A- P
                for (i = startx; i < n - offset; i++) {) n5 R0 F5 B0 p; X2 j; {, {: Q/ D
                    res[j] = count++;! L9 F. u& T4 u$ ^
                }. d- U; I- E, Y
                // 模拟填充下行从右到左(左闭右开)9 Z1 C( S" U: ^4 a7 ?
                for (; j > starty; j--) {5 m! G: e  X: ^
                    res[j] = count++;* e/ [: U& G3 J' k( K
                }
      l4 d# {" N6 W6 |- v, o& q# h, F! b            // 模拟填充左列从下到上(左闭右开); T7 d1 v. _* Q# ]  M3 s
                for (; i > startx; i--) {
    6 Q1 {! @/ `% l! v                res[j] = count++;  l7 N3 H  i' E& }
                }2 H( y$ r$ Z) Q6 G3 e

    ; I( {3 E+ X. u: j            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)0 Y- ^1 P2 F& n- U2 a; E
                startx++;
    ( Y! m( w1 C' z# N7 P            starty++;
    , w9 p; L! R: @9 f( A9 F& F% F+ H8 t7 i9 @
                // offset 控制每一圈里每一条边遍历的长度1 |. D; Y# w8 n) E. ]
                offset += 1;" B' H5 D" Z1 W, I  a) T: S4 d  s
            }- K$ F% E& e: O9 f' a/ m0 g- [

    " N' M+ _* v4 w* R& E% B        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值/ H) m" N0 H% E; }/ _8 W
            if (n % 2) {& U: W( o+ h5 i* g# c
                res[mid][mid] = count;4 k* z( @6 c: F& R: x( N! ?' L
            }
    ( k, r; ]7 T/ z: r" E        return res;
    1 k" e; j: t: U    }
    * X8 @, I& }9 q};
    ; e5 ?$ U% a5 w& {: [0 w* {, ]  d) i9 A9 S  w0 k
    ————————————————
    ; X, w3 U  g3 }* e8 p6 U版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 M' H, N! F, h- g+ I* ^原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039! E8 E; x3 k% `- O
    4 `: q/ s4 O- p& |: `
    ( w. q0 A& A- ?9 b( U
    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-10 17:26 , Processed in 0.988995 second(s), 51 queries .

    回顶部