QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1995|回复: 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
    数据结构之数组练习
    . y$ W( t* k# m+ `3 \0 |7 n% L4 e7 ?1.leetcode704) @1 E! ?3 J; a9 h. S) `: s
    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。* g0 i# H$ F) t3 n( ^5 |1 m  S
    / W( h9 ]6 T' ^5 s5 ]
    题解:升序 数组# f- _/ \$ ]7 e6 A* L, _

    ) u5 G/ j% N) ]3 x. [( K6 I/ t方法:   二分法/ e! T" k# o7 }/ q. B' U

      O/ u' D, ^* u4 c% \2 _思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    ( H& d0 i. w/ K0 d
    * |* X0 O3 W& x$ q1 I3 Y比较nums[mid]和target的值:& a9 c" k% {+ h, O% s4 v

    ' [4 z: N9 [5 W* Q5 w, B* a3 }: s如果nums=target,则下标i即为要寻找的下标;
    + q, }3 x0 f5 b" k/ {1 x- \/ `8 F5 T9 Y* T
    如果nums[列]> target,则target 只可能在下标i的左侧;
    $ `2 A! \% p( f+ M; h
    ; }+ ~9 B# X( V3 T' oclass Solution {+ O0 ]+ `" O! S* P5 M; z
    public:
    / }1 Z  u& g! u' `: Q4 o    int search(vector<int>& nums, int target) {: j2 i0 ^$ b- V2 Y4 R# S
            //区间[left rigth], A' D8 L5 P1 V' B& y
            int left=0;
    , V5 {  M8 F3 l" g3 n6 d        int right=nums.size()-1;  k$ o+ O/ O5 B3 F
            //结束条件 left>rigth1 }* F/ ^$ X) L1 B4 p& D0 R, t
            while(left<=right)
    6 ^! C' L: e' K5 u( Y  t        {
    & y7 I- T6 a* r) q7 b! |' Z            int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]5 X1 R4 J/ D* E( {9 u/ }
                //[middle+1 right]/ Y) i1 R1 J% ?" K2 J! J* }
                if(nums[middle]<target)
    / _) s6 w' u3 z1 Q            {
    . j8 o6 C  H7 Z& C2 g7 ^, D                left=middle+1;, x4 [  M: Y0 L9 y6 a
                }4 {' K0 x' _6 _* a
                //[left middle-1]
    2 R" E6 h( ?5 i) U2 c! S            else if(nums[middle]>target)
    % Y. Y, O& E+ s9 K. s            {
    6 E9 W& I# i+ f0 r                right=middle-1;- {4 R' R: y0 w+ C4 L% Z7 m6 b
                }/ g5 @. d8 n: I- O
                else{; L8 b% Q& W8 ?# ^4 Q8 H3 q( u
                    return middle;
    $ G5 t& N3 s) K! }# T            }4 l* L) L" ]0 I

    & z. H2 p0 T0 [/ q$ u, p9 K        }) d" Q2 w: a* a  [
            return -1;
    " P$ j$ O$ T) c. p( @6 E
      u9 ~: ?/ F) }2 x' ?    }! }0 N9 D, b& \# `+ A6 k% P4 M
    };6 l7 X  W9 R8 L3 ^

      K) V+ r$ G% F5 W注意:* f3 {3 ~7 X. G
    & @/ ~  y; h( u3 k: C# F- Y2 [; R0 d
    (1)设立区间为[left, right],终止条件为left>rigth- Y. Q$ r) X# F- A- C. s
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)" Y  ]2 j+ N  L$ [/ g" |
      (3)    通过改变区间的左右值;复杂度logn
    , Q. P# B0 J" e; |! Z$ Y  @: Z" D0 [4 r6 ]) I& ~/ k- a
    2.leetcode 27移除元素- E/ o4 N$ w4 t/ @, X
    给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
    + ], E* @$ `7 T9 q  C+ W
    3 c% k2 `+ k$ L/ f2 |不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。6 U+ O' O' C7 E" v: }+ f
    , a( w8 v- g% R/ J8 R
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。% A/ U" |' i# |: C2 p

    ' b- v3 W' I# A7 N+ T! W1 R8 K% F示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。! l3 K4 v) _1 @  w
    " D* K1 }3 r3 Z9 J; J1 H1 r
    示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。+ M. Z7 N: b" N0 x6 G! e/ }/ N

    5 ~8 }9 l$ y8 ~! M思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
    % X4 C+ D- x* `2 h, r3 l
    4 g0 }' L! d5 E* ~  i方法:双指针7 Z& Y2 ]. u0 q) ^8 b# ~

    ( V) m1 n( n4 |# ~" b% _class Solution {4 t% l4 e5 x2 Y, Y8 k
    public:
    & m% T3 v5 T% {    int removeElement(vector<int>& nums, int val) {
    . g! k3 Q- y4 z8 o3 Q1 s3 g           int solwIndex=0;
    ; ~. W$ Y7 J6 }, ?& z           for(int fastIndex=0;fastIndex!=nums.size();fastIndex++), L5 K: o8 D2 g
               {
      k0 j3 u, B9 Q  S4 @  p4 ?8 S               if(nums[fastIndex]!=val); z: C4 `0 K/ c: ~/ F- [
                   {! N$ ^! @7 k0 A7 q3 T
                       nums[solwIndex++]=nums[fastIndex];
    4 n2 N1 F$ Z% r) B               }; b6 z; s/ f2 E3 D9 k8 \
               }( e' j. u- M( y) M) q
               return solwIndex;; h# \( }. x* e4 ]: y4 w! b2 j
        }/ N# S1 Q' A, J
    };
    4 e1 }7 y3 k- Csolwindex:用来覆盖& q1 \" w9 q2 z' h4 ?' z
    & t$ k  L* ]% a1 L8 \
    fastindex:来找删除元素++
    7 S- B6 l) b3 s1 A; s
    . T! w; n7 X: g# H1 f* `0 w' V3.有序数组的平方2 L  U4 Q& x* @" ~
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。1 h- @5 j% [. {: `+ ]
    + r% w9 h) h# P) B! |1 u0 b/ D5 J
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。! f3 K. e- e; H8 |' K( N( J

    + |# n2 a. z9 r- f5 f那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
    , Y) \- @$ p9 h4 }- v5 m4 Y
    8 k+ _: k4 q9 }4 q此时可以考虑双指针法了,
    # p( N4 _. b8 R( ?5 T, s$ P  L( Y0 E; Z
    i指向起始位置(负数),j指向终止位置(正数)。
    ) q2 C  D: ]" {6 ^; P2 m7 _7 Z& Q  t7 B" x2 S
    定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
    2 |( N4 D3 |* K% ]! e9 O7 V! N5 _3 Y& Z, I, o  @% W
    如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    ( o0 K/ h: z2 W1 L' |: }0 ?5 Q: m$ ~& e
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;' G$ n/ A0 k# c" l4 y

    6 W1 ^9 w+ R4 k5 V' Q; C: wclass Solution {5 V( S: m! a0 d; I
    public:
    # z' z) A4 k5 L+ \) G    vector<int> sortedSquares(vector<int>& A) {. \# G' N: Q, G) b0 c& m: e! y
            int k=A.size()-1;' i. y$ V3 n6 ~* i# b
            vector<int> result(A.size(),0);3 b& c' K  m) n9 g  V( M& a3 ?
            for(int i=0,j=A.size()-1;i<=j;)
    ) J  I  P8 O# l7 y$ e: T        {
    2 C- e% S8 }1 k3 s/ R  ^            //遍历一遍8 y% c0 ~5 D8 I2 O) D0 P) x
                if(A*A<A[j]*A[j])
    % s4 a8 |3 w4 `+ }7 ?% t            {% t$ p0 H. d7 f! n, f( D
                    result[k--]=A[j]*A[j];" }+ N+ G, p9 T" G) k1 L2 {
                    j--;
      s( {+ M& \4 T6 X9 y5 i( C7 ^            }1 ]5 C, G  s: U4 h* m
                else5 w3 X# l8 s0 U# {0 L' e
                {* [1 }# B) `  c' T% d
                    result[k--]=A*A;
    9 V, n. x( s: H( K- D+ Y                i++;
    $ o7 E7 R& r& {  ~            }
    8 c! u/ s1 q+ d' h        }  V* R, b$ _% A( `+ l
            return result;. p& D8 R1 _  `6 v0 v& L$ j

    0 x4 v- I8 g; a0 v4 B    }
    % O, U2 n* {1 ^/ f% l};
    , r  ?$ b7 t( o6 T6 Z& X8 q. \& q+ K4 x
    4.长度最小的子数组. ?, [- N; P) |3 N+ [7 |
    给定一个含有 n 个正整数的数组和一个正整数 target 。
    ' l: W. ]4 E8 g
    + Q- R3 u/ \9 {找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。1 n% s# Q6 y/ g7 Q' P

    9 Z# t3 `7 }0 C% \5 m1 a- n0 `方法:滑动窗口法5 o2 n( w" J, J, Z

    . J5 A' n% J& I/ r0 ]! k就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
    / h& \3 ]% ^5 M
    5 Q2 }  i0 J8 a* O三点重要:
      c8 H0 J& h  w$ V: v* g6 H( n7 b* y7 c; j* X9 B) F6 Z! w
    窗口内是什么?5 H5 ~" q* d! K! P
    窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
    . V1 Z5 X  G3 S" D! L如何移动窗口的起始位置?
    ; i+ d0 |/ g  y4 @2 `& c窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了5 X$ H/ v! p8 w
    如何移动窗口的结束位置?
    : I# b3 \- N0 i) k; k8 _窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
      {' k6 C' d# v/ s9 g+ y$ l0 i. Z0 O. D  ]* q
    代码如下8 B# w9 b$ s" c* z  \' V. d+ q

    3 v# w) i( A( u9 @6 s; fclass Solution {
    . P/ L& U2 K, B0 ^public:
    * j7 Z7 W! N  Y) ^6 I    int minSubArrayLen(int s, vector<int>& nums) {; `& n! S0 I( k! C9 c$ l& U
            int result = INT32_MAX;
    2 z; e. ^+ ^  Y, ?# K7 \        int sum = 0; // 滑动窗口数值之和
    2 H5 D' S$ c. s- C( U6 v: A! v        int i = 0; // 滑动窗口起始位置
    2 E5 t+ i4 D% @( c6 v        int subLength = 0; // 滑动窗口的长度: v' k) X8 c4 `; }3 n
            for (int j = 0; j < nums.size(); j++) {2 O0 v& }6 K$ m+ v0 E- [2 q  @
                sum += nums[j];
    - I) ^0 C% ^/ z            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件1 z1 d0 e5 n9 s+ F, f% V( k) c! z7 R
                while (sum >= s) {9 B7 v* Q- ]( o: m2 |; c4 P+ Y6 ~
                    subLength = (j - i + 1); // 取子序列的长度
    3 \4 b' n2 i7 A! x                result = result < subLength ? result : subLength;//一定会赋值
    ; U. p) F# U# N/ c                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
    % ^9 [) n6 ?2 L, _            }
    ! c, Y8 k$ T  [( }1 P. ]' T& y4 S        }
    : n& Q( Q0 R. N/ }1 k$ j/ ~        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
    " U1 c% Y' V7 u- p5 S        return result == INT32_MAX ? 0 : result;
    : E6 ]$ I7 X$ y+ l# ]7 M    }
    0 S% @$ K/ y+ ^* J};
    4 u6 p3 O9 P: D5 O# I3 x
    3 F( \0 w; y, _+ `7 q一旦大于,就减去左区间的值
    , O2 F1 h, ^" _3 p4 w1 e0 ]. l! N$ E/ ^8 m, g  ^8 n7 z# U( j2 |( i- E
    5.最难题螺旋矩阵||; Q, F) u5 d: z9 c* o$ X1 m' Z
    模拟顺时针画矩阵的过程:
    6 o" f, J9 c- Y$ `  R1 U; C) _; Z/ \: i4 L) P6 g
    填充上行从左到右" a/ l/ d4 |: y. |
    填充右列从上到下
    / @9 m# t/ |" ?9 C0 V: q填充下行从右到左! d+ _, d  W1 P1 a) x
    填充左列从下到上+ _# j6 \; r( X. ]
    由外向内一圈一圈这么画下去。+ J; o* v' i& G; [, O: i# ~

    * B3 M. q3 h. b8 U5 D8 d  F( s这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
    : N& n1 F7 z  A! g; q' A
    ) I1 n* Q1 R% t2 b# q+ q9 W- n$ ~, r4 d' c; F
    9 f2 `# s" [" w/ V. n' d9 O

    - j( D" _/ ~: j2 R, z
    8 ^/ S" m( C# P/ [class Solution {/ M; P) E5 c' }0 p
    public:
    - V& L/ Y0 O0 o' ?    vector<vector<int>> generateMatrix(int n) {6 i+ u) _3 u6 j
            vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
    ; R3 N/ k1 P6 b2 s3 R        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置6 G. @7 O- J4 U1 Y/ F+ z$ s. t
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
    9 @. \% \( R- l9 Q5 q        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
    4 v- A* \) z' Y8 w        int count = 1; // 用来给矩阵中每一个空格赋值
    / ~% ?4 o  W3 u" H, P! ]        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
      b" s( z: E1 c& K: p5 W/ w  ]        int i,j;7 O  y* A( N: H1 e. v  ]
            while (loop --) {' m* T/ }& X4 `9 o! i/ f2 s
                i = startx;! d6 ?1 F6 H5 {& Y+ V* p2 \
                j = starty;1 i# v; g, ^' F8 j8 ~. \
    . B# M0 n4 v% h) T& P
                // 下面开始的四个for就是模拟转了一圈, u+ P8 R* ?9 `8 J& I0 G
                // 模拟填充上行从左到右(左闭右开)2 q) P2 ~" E5 c0 M
                for (j = starty; j < n - offset; j++) {# d! M: z$ N2 [$ G1 h5 T5 y8 b3 }
                    res[startx][j] = count++;6 R- H/ F0 F: u- O
                }% J; H. \, s- ?# Z& L
                // 模拟填充右列从上到下(左闭右开)! U( ]% i* V7 b4 x/ }* j/ c
                for (i = startx; i < n - offset; i++) {+ k- q1 O, k' J( b5 b4 r; T  O+ s
                    res[j] = count++;' q- }, |# U' B0 w8 i% z) a  D) O
                }
    ( K1 A& F* `6 W7 t) M4 a; ]            // 模拟填充下行从右到左(左闭右开)
    2 t; ~* H0 |5 A) X4 Q6 r+ [( y! c            for (; j > starty; j--) {9 }' Z8 ]3 g: Y, V9 ?) W$ @3 n
                    res[j] = count++;4 s3 i- |7 T* ?/ D# e2 D% g
                }
    * H% \2 a7 c  Y, ]) M- X" P            // 模拟填充左列从下到上(左闭右开)* q1 E. m, h$ R3 s9 p0 }% O
                for (; i > startx; i--) {( E; M" s5 L+ w7 K
                    res[j] = count++;
    $ F$ w$ c9 N% c5 R& _            }
    ( d5 h# a! Q3 S4 {0 N/ [
    ' D2 F4 h3 E$ i3 ~. E3 _            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)* q* |2 M/ ~3 r* [4 z
                startx++;
    * `+ P, O; B, R+ H5 ~- y( V            starty++;
      Q7 u7 \5 u* l- o9 s& d9 J+ ?* M
                // offset 控制每一圈里每一条边遍历的长度) d3 f6 d4 B# A4 H& y/ J
                offset += 1;3 }/ H( ]3 U3 y# L/ k
            }; |& U/ n7 {9 r1 ~$ k5 n9 N

    , b& K; h6 u) }, K        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    : R0 b0 R" w! U! l3 c9 V9 s% z        if (n % 2) {
    + S+ {* W/ H, }" t4 g' q            res[mid][mid] = count;6 f! C/ B3 A4 Y1 J
            }! V! v2 Y; R3 j. S
            return res;
    3 ]  p, k3 Z4 v: j8 L/ J    }! E. A6 B- C$ v0 V
    };# x. E& k' a9 A5 I* O! G- {
    8 q: f2 A$ h) d' B, ?
    ————————————————
    9 R2 y, A8 Z, }- T- a; _! p版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。3 l; W8 W) w5 B; B' Z
    原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450396 ~) s& o& I0 W0 ]
    , O! t; D2 {4 p6 P

    ; z1 @; t- S: M0 |, ?1 @
    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-14 22:59 , Processed in 0.464444 second(s), 51 queries .

    回顶部