QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2039|回复: 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
    数据结构之数组练习
    " E0 H, E( q% V1.leetcode704
    / Q& @+ a- Z) B3 D4 x: z( d1 Y/ h给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。, d/ q2 U5 U- \  e, H' [

    $ P$ L# E3 A1 s$ U& g/ j2 o2 v. {题解:升序 数组
    ) f0 y6 G4 V4 K  C4 \9 P
    / v( S+ P7 @6 E: k) u) V7 i/ d% [方法:   二分法
    - ?; K! {9 H" d5 L" r3 M/ R; G# P; v$ d, N
    思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
    & S+ o, \. {/ ~8 v) c) I5 M3 `8 V- g' u9 d, z# e6 y* b, g
    比较nums[mid]和target的值:6 K2 C) s: C$ ~! o, ]+ Z+ z

    1 U" V, u- q6 }3 D' X8 a如果nums=target,则下标i即为要寻找的下标;
    , l' n- S+ C9 q/ Z0 N* `8 H) T3 ?: v; z- A: B' }
    如果nums[列]> target,则target 只可能在下标i的左侧;3 b% I* g' Y1 F8 K! X7 G- j

    5 N7 f3 [/ e9 ]4 U2 Lclass Solution {
    % N! W2 C& r) {" g' [. c# Opublic:8 h. L( {* Q8 O+ |
        int search(vector<int>& nums, int target) {
    6 t) a" P+ O$ r        //区间[left rigth]; ^9 N+ m$ `8 V1 a8 r2 t
            int left=0;
    : i, u0 S0 D9 T5 Z) S5 Y' q        int right=nums.size()-1;6 K( d( w. \1 \5 g) s
            //结束条件 left>rigth' e7 W0 [7 y+ a$ T$ |/ Q7 C
            while(left<=right)
    9 N* c( w3 c* E4 J$ {9 \; A        {* T& `; i$ }3 j& |1 ~
                int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]- s% T8 w3 d, P: p/ J
                //[middle+1 right]
    1 J) ?  M% p2 @9 ]* E1 w# `1 S# Z            if(nums[middle]<target)
    . {  s, O% K: a; i% j# u            {2 \8 b  M" p% {8 v/ G
                    left=middle+1;
    / A1 |# E8 C( a  `- k. b# Q            }
    & M9 _7 Z( U( R            //[left middle-1]
    ! I+ }+ c1 F. t* E) p3 C1 C8 Y            else if(nums[middle]>target)' F, z  r2 f4 c( O9 h, n
                {
    + O# `1 T  w. R. e% i# R                right=middle-1;
    3 K9 G; G8 S2 {8 f; P: U5 K. A            }
    8 y) D! P) K1 R% v5 S; ?            else{
    . a' ^% g) k. f2 ~! ?1 s1 B5 Q                return middle;
    0 O3 J% E) x2 G' w4 _            }
    0 o. {: M3 P/ F0 Y5 u" ^( |  l& @
    $ P1 L3 ]0 a8 B) u+ o        }
    # {9 O( ]( E$ i. V. g+ O        return -1;: n) p, }  |# a7 M5 G

    ' i, U) n# c! f4 J    }
    0 e1 k" L' s2 X4 y& h};( [# k5 L0 D5 _6 k$ r6 ~
    ! Y% B1 Q: h* J4 S
    注意:3 f9 i6 R% g" B- L, T
    $ |) J4 B* H/ x" c7 x0 O" T0 h
    (1)设立区间为[left, right],终止条件为left>rigth3 r; W- m1 }& l' r* K
      (2)   (left + right)/2==int middle = left + ((right - left) / 2)8 m0 f& d9 V) F5 Z" k! E
      (3)    通过改变区间的左右值;复杂度logn! G1 Z- s8 a: N' C! `8 |0 r
    3 x% w) e. J% Y1 \& {' Y  B6 @
    2.leetcode 27移除元素
    * g/ S3 m/ j7 Q7 q( d" s6 @给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。5 x% U& w' T  I' ^) q
    2 a+ _/ a, C" f& ?" d7 @( D
    不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
    ; F' y, e# a6 c" t3 f' F) `0 J/ k# o4 I5 M- P% i
    元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
    * z" M* B: v6 i5 W) u. {* \% @" z
    ) v& C6 u3 K0 y$ G; j示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。! H" T& C9 H* l' z5 V! e

    / p+ ^# N, \% {% T; c0 j" \示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
    ; I+ \; b# @- K5 w+ ?  @6 g! m# o3 E# H6 [
    思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。. J- _* e  G3 y. k! z) J
    / ~8 u& G; j7 c1 e! G# Q& l$ L
    方法:双指针
    ; V& ^. Y5 ~  D8 J3 g, R
    9 E4 p& M' d9 N% ]* L6 M( V% V4 `' jclass Solution {% C; j+ L  U0 w- Q9 E; p8 O
    public:1 k+ V: o: D  A" ]# Q
        int removeElement(vector<int>& nums, int val) {0 E$ j$ |; T3 B2 O. P2 C
               int solwIndex=0;" Y+ K# F7 c0 M( ?1 w2 {
               for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
    " B3 Z7 m2 M* V8 p6 j; w0 S           {
    0 G& d" {" a  }$ P               if(nums[fastIndex]!=val)! V8 G) U2 L, S* A4 O5 }+ L7 p
                   {
    ) |; e4 ?9 |9 ?                   nums[solwIndex++]=nums[fastIndex];4 y( o* W, y: c: ]& a7 m. v+ H1 H
                   }
    6 f% k* ^) C4 `0 y           }7 ^% j5 A4 D5 \3 |) f
               return solwIndex;& Z1 o% t6 Z3 D' g  k, S
        }
    " z4 {0 X& U5 ]};# U: a. J/ T4 x
    solwindex:用来覆盖) {4 h7 Q, S4 c! k

    ) k4 U# w, j9 S: K' D9 g- Vfastindex:来找删除元素++
    ! M. B7 q7 B6 z6 Y+ \" @8 c+ J+ J$ L# D+ [. s# ^5 w
    3.有序数组的平方$ D. E0 ]7 S$ r# L% Z4 B- @
    给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
    ( m' }/ _8 c) G' V- M* z& k, x+ U7 o% e* [7 ^5 G  I- ?
    数组其实是有序的, 只不过负数平方之后可能成为最大数了。- l" A" l# q# N8 V8 C
    & \3 ~' c6 O7 j
    那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。% r$ n$ G4 Z8 O9 {( y# r# u( [- O
    / p; R7 ]6 S! V  r$ N
    此时可以考虑双指针法了,- Z: }- m  r2 q1 V8 \  c

    1 a0 f5 z  Y7 C" ~# @) Z9 ki指向起始位置(负数),j指向终止位置(正数)。
      m0 s" [3 }7 p& `3 p6 a0 L  y
    - w/ F3 R0 ~) [" l# C. `定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。5 }7 h  {2 f9 [8 L4 g0 Z; X

    + v  P! y8 z/ o" S9 p- d如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
    $ y  o+ z5 G) u0 @& ?2 C3 @6 A9 |3 {
    如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
    ; L, n" C; p4 d& J3 Z
    9 T1 L4 A6 ^) V. M. v7 Fclass Solution {
    % S' \0 G/ W+ m/ c4 y0 f& mpublic:" V5 Y! Q7 U/ l4 H, ]  J/ t
        vector<int> sortedSquares(vector<int>& A) {
    ! |# q. x" T5 ~/ W5 D        int k=A.size()-1;
    ' J. d! ^- @2 u# L( G        vector<int> result(A.size(),0);& C1 [$ M9 t1 ?
            for(int i=0,j=A.size()-1;i<=j;)9 _# ?4 O  |6 l' K
            {7 o9 p6 a+ H+ a
                //遍历一遍
    8 p! K1 {. P" R1 o            if(A*A<A[j]*A[j])
    & N: Z0 X/ N9 L+ D            {5 W1 ~' d" l6 w6 v7 W1 d$ F+ D/ K
                    result[k--]=A[j]*A[j];
    & x& V+ e( `: I; y                j--;+ ?( a/ p2 ]/ q" F5 ^
                }
    - \! x6 ~" |$ ~            else
    : {$ B& K  _+ N& E& k) [) c            {
    4 f+ ?% H  d+ r2 e                result[k--]=A*A;
    9 }/ ^% P, m/ k6 j- c, A7 N                i++;
    * F# b& T0 e% j5 _" `' {% ~; e            }
    ' A- R0 z; o4 p        }
    / F- w$ z5 H, T' s- e        return result;' N. d! l/ S. \& x- ~% L
    + K& G: L/ f" R- @+ y
        }
    ; a6 V3 n* l3 w3 t};* T$ U' J( o: J( l
    ; y  I! H- p% z# Y
    4.长度最小的子数组
    - k) H% Z9 y0 z' h, V+ P给定一个含有 n 个正整数的数组和一个正整数 target 。: h' d& W. A- s% i

    % K2 d) |# F/ ^5 d, f9 Q' r; z  @: s找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。1 S4 j) D3 j) m6 x

    % H: j5 O, _2 p  M* N, x方法:滑动窗口法
    3 s; D5 @6 \4 M6 o9 Q# e
    0 b" V- y* x6 P就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。* N& v7 y" a; p. o- n. R

    $ x* f/ y5 P$ H- _6 B三点重要:
    9 F! r/ Q) Z( P0 F$ {4 j( s
    1 H9 H- k, {: z# J; y9 D窗口内是什么?
    * o4 f8 m* D/ }  L, Q窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
      O- n! y8 a+ n4 F' k, D如何移动窗口的起始位置?; H: a. G+ W7 O2 Q/ F0 n" i
    窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了$ W& _; D: r3 o: t, s% t
    如何移动窗口的结束位置?
    8 d; t- ~/ S+ U/ H) v; G窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
    ( A6 H9 O6 k6 D9 o% y9 y7 s& I/ r' o8 C
    代码如下$ f$ D: b8 c" V" W+ W/ e

    4 W5 T& {8 z2 T- G* |& wclass Solution {
    - V& F8 G0 h8 O( p& R  m# ~public:7 {) Z. w* e- w" u" J
        int minSubArrayLen(int s, vector<int>& nums) {
    1 g5 k1 w2 e# H        int result = INT32_MAX;4 P" p5 X. a1 k8 O" M6 G
            int sum = 0; // 滑动窗口数值之和  N) U7 J8 z5 T! j
            int i = 0; // 滑动窗口起始位置2 R! \! e# N, ]9 k' t6 u5 `
            int subLength = 0; // 滑动窗口的长度. P5 h* ~( D, i3 L1 M
            for (int j = 0; j < nums.size(); j++) {
    * x  v) K1 U. d+ T) n            sum += nums[j];1 p/ m7 H; {0 X/ E1 Q& ^
                // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件' ^0 }8 ~4 n7 b: I' N& d
                while (sum >= s) {
    ( I$ N1 O: g0 C6 j. s4 {  |, d                subLength = (j - i + 1); // 取子序列的长度
    / Z( E0 k/ C7 c( u+ Z5 X# a                result = result < subLength ? result : subLength;//一定会赋值
    " [+ q# v' F4 `3 }- D% u                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)) R: ]% E3 E3 v* {, ?
                }
    ; N4 ?1 d2 t  k  D% h        }
    ( `/ O! B% T4 U( {9 j9 T  X5 _/ s/ _        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列: Z* f5 A1 D9 g( z& k' @) Q- \$ S
            return result == INT32_MAX ? 0 : result;
    1 A4 B( D  L* ]& N. s$ p    }( e6 N" s8 R2 ~5 D  Y
    };
    & l% M3 _4 W! w' @8 r& |1 d0 r
    0 M! |! M! G7 y3 A% @) A( C8 K4 Z# A一旦大于,就减去左区间的值
    5 k: h- v2 e, k; u) ]0 |: @' C1 P% @- g# ]# Y. h, M2 Q) u' ]9 `
    5.最难题螺旋矩阵||; `1 H/ [) t  K( D' S/ F
    模拟顺时针画矩阵的过程:- i9 U, M( n0 Z# S/ Y8 F  ^8 d

    $ P. u0 v- `  x  o  _. x填充上行从左到右4 s4 v! d- x, H# G7 V* F& I
    填充右列从上到下8 B# r/ ]: N+ J4 Y
    填充下行从右到左
    " k0 n3 C  H0 [( {) C填充左列从下到上
    # U# k7 u7 c' F, l由外向内一圈一圈这么画下去。
      I; @4 d" y& A% D9 T1 Y' y8 F8 B4 ^  Z# n* I+ y! D
    这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。: ?! e4 T1 h. _0 t7 p
    8 U3 c6 \1 O! Y0 Z
    # N9 z. j+ W  g: j

    0 G6 o2 I1 h7 N+ V" B' u$ [1 |( [8 o7 q& k* Z2 }( A5 f7 S
      J5 g3 A3 d% P  d
    class Solution {
    # H8 {# Y' o! |4 M! W' E) a& Xpublic:; A5 H$ B# A/ v2 Y& l$ f
        vector<vector<int>> generateMatrix(int n) {
    ; M0 e/ X: K2 j1 k4 B- ]        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组. L; H$ {# ?( i, k9 v; v( H  D
            int startx = 0, starty = 0; // 定义每循环一个圈的起始位置: j9 U, _9 H( k; P$ P
            int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理0 [: e; ^1 x8 Q3 @
            int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)# ~  e* B  C% z# n
            int count = 1; // 用来给矩阵中每一个空格赋值- i" u0 N! J2 B$ T: u% x# @
            int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
    5 i8 }4 }  A" q  X( R/ x# V- H        int i,j;) _7 f: m$ p# _) r" A6 @
            while (loop --) {; k' h: X, l) X6 @  n
                i = startx;6 u  ~5 \* a) {( K3 @2 X
                j = starty;
    : Y/ E+ x" h. J0 G  f$ n( w" S; K4 `* v. C) d! j; W
                // 下面开始的四个for就是模拟转了一圈
    3 `% E6 s3 ], q7 a/ R4 f- r3 N0 k) N            // 模拟填充上行从左到右(左闭右开)
    2 \$ Y8 T2 y3 @/ R- M: i) d            for (j = starty; j < n - offset; j++) {
    & y$ @0 l& r6 [# p- L                res[startx][j] = count++;- C7 w1 G' W  p4 P* o: S; M) u
                }
    * c& A' F$ A3 W' f            // 模拟填充右列从上到下(左闭右开)7 I3 ^; X2 A( [/ h6 e; w' f/ R
                for (i = startx; i < n - offset; i++) {
    * P' k" H& P0 c, s0 l                res[j] = count++;: C3 Q, K  _4 ^0 @. `# Q
                }
      J6 G, H  h% x            // 模拟填充下行从右到左(左闭右开)
    - X7 r- y7 ~; p2 ^9 G+ C            for (; j > starty; j--) {
    5 F# Z7 M. x) c6 M3 z                res[j] = count++;
    " J- r0 f9 e3 L; \; u) x            }, D6 W6 D" \6 r4 M
                // 模拟填充左列从下到上(左闭右开)
    7 K* \% s4 g5 ]" D            for (; i > startx; i--) {
    * s* _+ A) `2 G" ^; q" T                res[j] = count++;
    6 a' u( }' f: N/ x+ d4 b3 m# `            }
    $ e) ?/ t: z' p* E% e- V6 b6 M8 f2 v
                // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
    ' Q+ r* B; n* r; S3 }1 \/ w" _            startx++;
    3 ?% o) ^$ {5 F3 U5 ?3 w: C" E5 b            starty++;! a7 l( b! t3 a. L! X9 m

    1 d/ u1 Y$ r1 L% ]8 w# ]            // offset 控制每一圈里每一条边遍历的长度3 L7 F$ z2 h6 X8 [! M: O- d
                offset += 1;
    8 ~4 M! C* L2 l& i8 h1 Y        }! N+ F8 _  N- m0 f3 n

    7 Q  E5 f1 ?9 c, r6 N1 D1 U# M        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    . B! l% R: k5 x3 S* A5 f        if (n % 2) {3 v# c' V( l# m# [
                res[mid][mid] = count;
    $ z" A. F( ^" p8 d  `% k2 y        }
    ) r, N1 [# z6 H0 B3 q3 J( t% Z; n( X        return res;
    / |1 n' u' ?6 ?# ?; D  q5 o    }# {6 a6 M6 @' ]8 z6 D
    };" L0 Q! W" s5 e; p* g
    / I: a- T* ]& e% C6 q3 y# L1 _
    ————————————————
    2 m# D8 F. k0 s* w版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    2 l! g5 l" O' p原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
    5 V+ G6 P& F; [$ l5 y$ v; {' K; h+ R
    . {' ]  m- ^. b- D" X4 [
    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-30 04:13 , Processed in 0.406791 second(s), 51 queries .

    回顶部