QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2005|回复: 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 F5 Z; [; G& b* Z8 J
    1.leetcode704% m0 h0 V0 v4 X: V& t. b- Z
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。# R4 B$ e0 j5 ?: h7 Q! e. P5 w* w
    ; u7 c- i; c+ O1 J3 h% T/ w3 U
    题解:升序 数组3 y. b2 R& i" u+ W  v

    4 \# G, y$ ^9 x0 ]方法:   二分法
    , {% `5 f8 K5 Q
    % Y" d: t8 X3 l; ]+ m思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    / `: r  V. L" Z4 ], h: g) x& W; z4 `& i; S2 j
    比较nums[mid]和target的值:
    ! L. u% c2 r) T$ I8 P
    * @) u! Q2 T5 l7 ?- L7 K如果nums=target,则下标i即为要寻找的下标;* \9 u$ T: Y+ X4 F- v7 b$ M5 i
    / d4 M/ z$ w0 E0 H) R, m7 Y) F
    如果nums[列]> target,则target 只可能在下标i的左侧;
    ( z$ ?+ f1 I6 L& j; d) |. ]2 P+ l/ B1 t9 m2 }; t2 k1 S
    class Solution {
    ! c" S, ^) L4 vpublic:- C1 H! [% H1 I# [
        int search(vector<int>& nums, int target) {
    2 f1 m8 Y, {3 G! B9 [        //区间[left rigth]$ ]- J3 G( z- D/ e* }8 K
            int left=0;
    : j, A) j6 F# A. F        int right=nums.size()-1;
    $ e* s# H( p" w* C        //结束条件 left>rigth
    4 C6 @" K  W! Z& n        while(left<=right)
    ( X3 L% b3 _) _        {
    - Y4 ~# T/ h4 s            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
    # o5 T7 ?# O' L3 |) E; d7 T            //[middle+1 right]4 s" a: g; ]5 N0 I  F
                if(nums[middle]<target)
    0 @  O7 Z0 X. B) ?8 t: M* ]8 G/ |            {
    ! V! k# u+ s( {                left=middle+1;# M- c* D* ^/ q5 ?0 O( H9 a
                }3 \# s* n2 m/ r( z4 B
                //[left middle-1]
    & M& _2 z9 ~' J1 V7 r7 R            else if(nums[middle]>target)9 O0 |+ m/ V& ^- s" x' j
                {" g  `: y* R  }/ Y( K( F
                    right=middle-1;
    : s' O# \* y$ Y4 [8 O            }3 g+ u* ?* r& X8 C. c' r, ^$ K( f
                else{
    9 O. P) A" K: q+ Y& U: v                return middle;
    3 s& `" @/ l5 v& Y+ G" E' O            }
    , u2 Z) @8 d& a3 Q* M& n# s8 r; q2 J0 r1 @, k
            }) A) f  g+ ~$ f! M; H6 k: t
            return -1;( C- i6 n6 n; L4 F. W% X/ g2 ?+ k
    ! |7 x3 R8 `7 C6 L; Y6 Y
        }
    4 e+ N& B0 G" Q1 @6 u, ^. Z2 X};
    ) Z, O' g- S0 p& I5 r3 L! M8 C0 |$ M) I# M
    & N" L/ U, P# z& L  o& K注意:
    3 T! v" X1 J; M; g3 }6 r& ~% p; D
    (1)设立区间为[left, right],终止条件为left>rigth  K% A4 f8 F* I: L( s$ o8 i4 u  A
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)
    * X. {8 W$ R1 u3 @& u  (3)    通过改变区间的左右值;复杂度logn  v+ c& i6 `" d4 E* s0 l) M

    7 F+ M1 r* W1 u( d; i2.leetcode 27移除元素
    3 {, k/ I0 V) Y给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。5 {& S0 g: _9 L! ?

    8 ~3 |1 `" x4 P3 G6 \不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    $ ?( H0 b+ ^! F: r% k: _: B: h
    6 Y9 s% O3 J& b5 ^  Z元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    : X3 [' e/ n2 l( |
    * h- H& _3 Y. K! G# Q1 ~) t' [0 o示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
    - k0 d- c9 ]! Q8 K: @) j$ _3 d2 `4 _( e9 x: ^: [
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。! c, q5 M" Z! X, U
    % Q. e; y" w' b& g5 ?6 W' A% R
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。, g5 a2 u8 x" C/ j) A! k2 T

      ~7 ^5 A1 Z: T2 t4 F1 s9 d方法:双指针
    0 t6 k+ I; M) ~+ u; t. k- X
    * ^4 x1 D# x+ Y* i9 i% Uclass Solution {0 d, C' E$ y8 _1 I5 I
    public:
    - o+ k+ A7 U3 Z. j) m! H: P    int removeElement(vector<int>& nums, int val) {
    1 X& J' F9 T$ T2 I. T5 n5 l           int solwIndex=0;4 [& ?, Z' k9 H: ^4 ?( j! M0 b
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)+ n$ s) e* m9 E2 w
               {0 U9 X$ I6 o% [6 d# J
                   if(nums[fastIndex]!=val)' B* T1 q9 O' y: I/ D
                   {+ L0 e% l% o# B2 x* ?
                       nums[solwIndex++]=nums[fastIndex];
    - j, I9 z) ?* m7 _8 y               }1 W) s+ c9 j6 ]& g; ?& ~
               }
    + m7 `; b. l, l; a           return solwIndex;
    8 E" D7 t$ o% k: W* J% ~3 ?8 w    }
    - R7 I2 W, S. J5 l" {! |};
    ( {2 }8 [2 e1 F2 y9 gsolwindex:用来覆盖
    ! I. q: i0 g, i9 {. {9 T* T; z. z) c- T" k: Z
    fastindex:来找删除元素++: z, r4 U2 \1 E% G3 K* b$ X) W

    . q* f; h# o. Z3.有序数组的平方4 ^5 V0 ^3 [2 o7 @" B) b+ z
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    # {/ H0 g' O' r' X9 h2 q+ W3 y  g3 H, r! }5 V$ \8 `
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。
    / x5 O" \& |8 N: a* w: w4 c5 J' |* R, j; Y) c! \* e  U
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。! w, g, s4 ]5 Y& B; W
    ! }: p9 B: K5 Z9 b
    此时可以考虑双指针法了,- A4 G0 `0 q1 A  F, e

    ; T/ A/ ?/ r8 A/ h/ u3 L( gi指向起始位置(负数),j指向终止位置(正数)。
    6 ^0 E: I, Q5 B$ d9 o. [+ T' _- n) R0 L/ f
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。; }' S5 |; ^/ V! J

    . ~5 \7 h( \8 d如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。7 l: p$ ^) A3 k# `/ Z/ E
    3 p) Q( i) r/ x1 u3 x0 m
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;' n0 s" G, a4 V# l
    2 A$ j; X* U& B& y$ M2 y2 I
    class Solution {, A2 o0 Z8 l$ K6 u
    public:! C5 K4 O' {6 e0 p2 W6 I
        vector<int> sortedSquares(vector<int>& A) {7 G+ O5 t! ^4 z/ f/ |" T
            int k=A.size()-1;. A" U- u% Y) O3 U, D
            vector<int> result(A.size(),0);5 D9 S3 y9 d/ a7 g2 g5 {. N+ e/ `8 A% m. N
            for(int i=0,j=A.size()-1;i<=j;)
    & g/ G; H! C9 s        {
    1 U# U. ]. ]  R            //遍历一遍
    $ o0 f0 k, Z, ]1 J; a7 w; l- l; G' M            if(A*A<A[j]*A[j])+ V+ a; K& |" e/ y/ u# q
                {0 I- W+ G& g: V/ U' _' Z+ Y
                    result[k--]=A[j]*A[j];  ]: h! G0 M6 s( s6 n9 _# r) O
                    j--;- d: {2 t" ^7 F$ f+ e( [5 E
                }
    % F) D% I, ?& i" M' v$ f            else
    % b) i) K/ f8 g6 e2 \            {
    % G) d' t) V- G% L7 q6 K                result[k--]=A*A;
    / r) B8 D/ \5 X# \, r+ n6 B                i++;* I+ P2 ?1 g6 I, f) Q* r1 \8 z
                }
    ; r! U( Z5 H) s        }$ _* p" \- U$ r2 `' w* e% U' t
            return result;
    2 e; H- V1 m: e) q" q1 U/ m
    $ v% f; l7 v# R2 ]$ @4 B    }
    " W  {' c0 r9 ]. y" Q};
    - j/ `5 q* t" S. z; g
    , S  V8 j8 [; h3 m7 n4.长度最小的子数组4 g: X! p$ R$ S8 E: c: v
    给定一个含有 n 个正整数的数组和一个正整数 target 。6 T' m$ V# N( T. l! X3 r

    9 |0 |: y4 G$ }/ w' o$ ?找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。+ I5 W0 r$ ?: T& X$ x

      p4 Q. i9 n1 z4 ~# H; J方法:滑动窗口法
    : J' Z' P# k9 l' c$ g# l0 Y; }, G5 _& u; t
    就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    8 V( I+ j1 f8 o8 N3 I, b% T$ `" \$ b
    三点重要:/ w0 t) ~  V+ W: g

    ! e8 y$ Y+ x& b窗口内是什么?
    % _% _8 D# \5 b7 ]( G  Z- N' h窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。! Q" ^. c% c/ P
    如何移动窗口的起始位置?
    ( M6 D# q& i3 M$ q' P窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
    ' Y. a5 C! g. M! n' p如何移动窗口的结束位置?
    3 d1 x6 p/ d+ T7 `8 p9 e& ~窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    0 M) M# p# K0 H& \2 ]
    : @" y3 }1 C3 s% @ 代码如下/ @6 u' ?3 m4 T( d/ W( w

    # h( u* I$ Z6 }9 ]class Solution {
    4 e9 F( ~9 ]. Jpublic:. J! N$ j$ D6 s5 z
        int minSubArrayLen(int s, vector<int>& nums) {( C0 z' D9 ~: s" c0 g+ f
            int result = INT32_MAX;
    ) C( t& N9 T2 B# _        int sum = 0; // 滑动窗口数值之和0 {* j* ~) `! e( Z6 i7 i* i, q3 l
            int i = 0; // 滑动窗口起始位置, G( ^3 G* [+ @+ n
            int subLength = 0; // 滑动窗口的长度1 z5 v8 g5 u# }' V
            for (int j = 0; j < nums.size(); j++) {
    6 s. C( t# W" U            sum += nums[j];+ }6 F# x/ B4 U# n9 \/ s
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件; |9 b+ I. I% f0 q* k
                while (sum >= s) {" B" ]- `( Q$ l
                    subLength = (j - i + 1); // 取子序列的长度9 s9 v& k4 ~6 x3 }
                    result = result < subLength ? result : subLength;//一定会赋值
    ; z  @2 I& E% X8 s                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)0 F  D' x7 K( I6 v
                }
    9 @1 s: f# o4 w+ o. S        }1 e0 W: R2 l' T7 s2 h
            // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    $ s0 p0 i; ]* ^; C( ~2 F        return result == INT32_MAX ? 0 : result;
    - a) Q4 Z, R, }! l1 m  n: H    }, f& d7 ~  ?: }8 k7 X  l
    };7 O$ W3 ]( b8 R  I, n

    ' l# R) _2 W& G! W8 C一旦大于,就减去左区间的值& G0 \$ r. Q; q( K, d3 A+ v; V
    " t' a) R( T( e6 ~5 p
    5.最难题螺旋矩阵||' a, d3 B3 X: O2 Q" F0 B
    模拟顺时针画矩阵的过程:$ V2 L% k! o3 z7 S
    0 Q8 x9 _) J( n$ [
    填充上行从左到右3 b6 p& ?; R$ k$ T7 r4 T
    填充右列从上到下
    0 R% o8 u. J0 i5 P. s填充下行从右到左" F. [1 O+ S- m4 G
    填充左列从下到上
    : c$ j: T0 r1 O& r1 J( C$ M- [由外向内一圈一圈这么画下去。& k5 b; i2 a7 F/ `
    , D" J' }! I# I& J5 C
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    9 n3 r; S. E3 I* s" m) B5 W
    & {  N9 P; H" v, [. y' o
    7 E4 z' _1 f. M8 ~9 D
    " f7 l+ i0 ^; |
    $ E/ N/ o6 o3 G- w  X0 w
    ' z; R$ i+ \2 jclass Solution {
    & d8 P3 \% o, P% D7 |: Z5 jpublic:
    * _) K! B0 q. O4 Q6 x    vector<vector<int>> generateMatrix(int n) {
    " T1 y4 ?. f/ L9 s3 Y0 b& `7 H. ~- w        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组9 l% W6 p# e0 ]# R3 t6 H
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
    ! |- ~( W0 R, `6 H( W        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    8 K( T, p& v, L# V' ^& F5 _8 g4 u2 m; _# u        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2). U5 j2 b3 x+ x, `4 C  m& x
            int count = 1; // 用来给矩阵中每一个空格赋值
    . O9 {2 a0 Y% h$ q; h2 D4 v2 _2 g1 j        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位2 v0 ]! |  v7 Q: Q' w% y
            int i,j;2 r/ B( }0 L& i+ l6 d
            while (loop --) {/ P0 ^7 e: X( Z' o- @0 c# c
                i = startx;
    + t  ?" ~$ R0 T/ {            j = starty;/ g! L) A$ n( I- r0 u8 `
    2 d* M0 [( |( v% L, o; b( [
                // 下面开始的四个for就是模拟转了一圈
    : O/ q+ ]+ W$ |: k            // 模拟填充上行从左到右(左闭右开)
    1 n0 c- ]* m( r& c            for (j = starty; j < n - offset; j++) {
    / f1 I. q8 |" W- s) {( D) e9 X                res[startx][j] = count++;
    * ~4 i7 r8 n/ D+ \& A, S- X0 i- Q            }6 o5 D& P% G& E6 N& K
                // 模拟填充右列从上到下(左闭右开)
    . K+ |4 n# a1 p* E6 c& \            for (i = startx; i < n - offset; i++) {
    0 F9 b! n; S: v1 v* X$ \: y- R                res[j] = count++;
    " i5 q) z$ b+ z4 {5 s            }" H. I' f1 ^4 o
                // 模拟填充下行从右到左(左闭右开)9 [, q( K2 j' g- b
                for (; j > starty; j--) {
    8 @' ?$ w$ y5 h  S1 D" P                res[j] = count++;
    2 K# K2 S; ], c4 V9 w2 g            }
    6 t4 e8 K9 u0 d. T9 c- R) S. N            // 模拟填充左列从下到上(左闭右开): ~. i- Z- e) I6 A+ g9 F% e1 g: t6 G
                for (; i > startx; i--) {
    0 D$ N$ G2 ?& j5 |+ ]                res[j] = count++;
    , f# b- i- P9 Q% r            }. D+ S0 F0 R* X$ b) S  s

      A3 F9 p4 c; [) j            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    ( h' l& b! b" I$ y/ n7 p  O            startx++;
    # P' v- I3 j$ R0 O3 e7 L            starty++;7 c! t# t; b, Q' ^

    , g9 V& X6 T: e            // offset 控制每一圈里每一条边遍历的长度+ J& N8 L+ i2 o! R
                offset += 1;: Y' ^" V; H, s7 P0 b+ e5 E9 y
            }
    % Q7 b; }7 U1 B+ b; m$ V8 h
    / z4 \/ S# y& g  I        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值! j; b1 {2 L0 A5 y4 a
            if (n % 2) {
    9 Q5 d2 A0 m$ ?( L, W; I            res[mid][mid] = count;# Y0 h( Q3 `6 |4 M! T2 o
            }2 B) D. k) D+ q' @. G1 k7 ~* ?6 T1 l
            return res;
    ! v7 u* I- b9 m. Z, @    }
      u* F# r" m4 j6 m0 x0 t};
    : R. K. c8 A& S9 W  u4 C7 v) [' z0 e( g9 I4 V$ H) w7 o' M
    ————————————————
    6 {, {1 j- I/ N/ u版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。2 r9 |$ w+ V8 r: B3 W3 l2 N
    原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450399 A- O1 F6 [+ H8 l0 ]1 F5 U" M, E

      W: L7 n, I$ R) O8 @% U( \
    ' O; ^$ O& L$ k
    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 06:32 , Processed in 0.335902 second(s), 50 queries .

    回顶部