- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563305 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174214
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习
" o: b& N S5 R4 H5 o* ^1.leetcode704! `. _0 }+ e% t4 {
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
: E. M/ ]5 ?8 n# q( X; P/ D: `
c2 s. S" i; |2 L/ F题解:升序 数组
# v5 E2 ^, A8 v- R+ L' z4 m; I! k, M' z. u. W
方法: 二分法0 N. o, R2 w' C# B2 K
4 Y; u8 ~/ \6 Q- Z5 J思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
, `, B& u9 I: ^$ ^, v; M j/ a2 S; g, o0 F) n. d5 c
比较nums[mid]和target的值:
* ]# K) P$ l9 y0 r+ g2 r+ \- H
# F# A0 Q2 M6 \. E+ G如果nums=target,则下标i即为要寻找的下标;$ A7 @0 n7 D6 n1 v7 O3 n3 Z) I9 p
1 _# W, i* i6 O6 j0 |如果nums[列]> target,则target 只可能在下标i的左侧;4 ^: [7 ]% c2 M) G3 ^
$ B2 k/ y- p. W! E! D J
class Solution {$ L( g+ Q' S! ~5 y( Y# ?8 y4 ]
public:
2 s0 L, s5 ~' W) h' c int search(vector<int>& nums, int target) { q! q* I* n0 Q2 S# z3 }
//区间[left rigth]+ K, _- Z& a+ h
int left=0;3 [! W; t0 B2 _% s) Y
int right=nums.size()-1;
" l3 @" f x3 V6 F0 ~2 L //结束条件 left>rigth
6 I* Y$ P: p2 q while(left<=right)4 H8 m. z2 A: j3 I
{( S7 x9 c8 i# g, j8 c% t# R3 `
int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]6 D" d3 Z1 J/ |% P0 ~' D
//[middle+1 right]
$ m: @, D% I9 G) k if(nums[middle]<target)
+ f. n( v/ o7 C: j4 \: D {
& S0 N/ V) L: K# S% j left=middle+1;
8 Y* d% `$ N* l4 o% r( X }
% \9 H9 k7 e t P5 H //[left middle-1]
: B: X8 A3 d* `! a8 H! S7 a- X else if(nums[middle]>target)1 K8 k8 m- h3 ~+ H4 ?
{) M( C* X4 _0 M7 ]6 d" ~
right=middle-1;
) h8 s: p, x, } }
$ K: W9 Y E( L: j$ v: | A& F else{
7 d4 J' ?0 C# A6 t+ @) R5 |" g return middle;9 o; Z5 K5 a( T
}
- b0 F% m8 k4 f" b( E
, }4 d ]$ Y! |1 t }: \% k5 Y5 C4 E& {! Q+ l
return -1;; n) I6 u- F0 i5 \
# _7 p" f/ y, r3 q8 t
}' `! }- i# b% k2 J8 n7 H: O3 E( I% t
};& n; G7 M, k7 L" [5 r7 W2 Z
) h, O* K- _' H0 P. o+ ]6 u注意:! n( ~, U- p6 e, K5 Q$ M3 w
7 d; @+ R; c! H/ \& f
(1)设立区间为[left, right],终止条件为left>rigth
; j) d. P7 z0 P, ~ (2) (left + right)/2==int middle = left + ((right - left) / 2)
# W( Q( E. a" Q; V+ P (3) 通过改变区间的左右值;复杂度logn% V. x9 h6 Y7 B. H# [% R8 i
& |4 n# Z) j7 G2.leetcode 27移除元素4 N8 |6 O' E- U
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。- Y8 F8 w, y. W
7 r, i; r: F+ C- y8 _ w不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。6 }7 y# @0 \, a4 m/ a8 D y, I
! `, u* I' t- Y5 A' q9 v- Y* W元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。, |9 d) [7 A3 ^: \$ K6 P5 S% \& y" T
( o4 j) y) B7 E r% Y( \示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。/ @0 Z1 @/ A1 C5 l
, V! E5 ~* U* }2 L
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。" W. G; a$ V5 l/ I' D. u
( _5 H* w b f6 c5 k思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
9 P J( v* Y( J: b" P$ G0 c: i" s$ \$ ~
方法:双指针3 l0 I6 ]0 R$ J0 H, x& O
6 z) h. r- h6 _1 K+ l' u" B
class Solution {2 o1 |% j) a/ M
public:
/ a7 Z0 Y: |) W5 v+ F% W+ r8 h int removeElement(vector<int>& nums, int val) {
8 F& n2 ?7 D/ p int solwIndex=0;
& y; \( X* p1 R0 B& B% J for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
5 e) Q( T; h7 s {. y2 P8 d g# Q8 q3 G3 V! b4 z9 Y
if(nums[fastIndex]!=val)$ B- \+ L8 r. v$ f) [
{
; D' w7 g' ]# w9 T& l- g nums[solwIndex++]=nums[fastIndex];
. x) `. i& \$ W( Y, y }
; S& x8 f1 h3 x* S8 o% a }
0 p0 m) D/ H* b I1 }3 ] return solwIndex;
A5 C* i" }+ Q; Q. {9 ]8 H0 v }8 S9 p! J7 k0 j3 `$ ?* l1 V5 Q+ U
};' S4 D" P( p+ E3 T
solwindex:用来覆盖
& P. k D1 d! W# j0 ]/ \, ?; K* o0 u! D* V( B8 I9 K, G' D
fastindex:来找删除元素++; ^* a! W+ ~$ G" K- m
: X" B8 f2 `+ q7 x( k
3.有序数组的平方4 d; y0 z+ c! q7 b
给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
2 b4 r$ Z; l: v- u, m" f9 [' S( [$ S% z; v; Z
数组其实是有序的, 只不过负数平方之后可能成为最大数了。2 \1 e- X) c3 o3 W# f$ u* p( k: F
+ B/ r' r5 ^& T# d& `) g那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。: w: A( V7 I$ P1 i; ?' t: y1 L
0 j' T- x n9 |( k) d% B) D此时可以考虑双指针法了,/ w+ c* |+ ]& g5 B/ e! Q
/ y. n0 f2 o1 x) N% g) f: z9 vi指向起始位置(负数),j指向终止位置(正数)。) _# @2 ^( x4 H1 G
6 O% @6 C8 ?5 y6 D
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
5 H, k* c- k( `$ Q. V. a' s6 P8 v: l+ M( M: x( {% X
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。* ^% k( @$ i) t E& D
8 f' M4 N* U; f$ S! U* {) z
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
/ S6 @% d0 l6 t% \6 D6 p
2 E' Z" f2 |/ R, D. u' F+ t) H e fclass Solution {" p8 u3 c8 S; Q: ^& z2 c! Z: t
public:
! t) l" ?7 g0 o vector<int> sortedSquares(vector<int>& A) {
. m6 d$ s8 ~6 [ int k=A.size()-1;
, k- y" H3 J' Y vector<int> result(A.size(),0);& S/ R* ], [* x
for(int i=0,j=A.size()-1;i<=j;)* f6 Q2 v( [! E" W3 _" _/ n
{; p9 b1 N- K% w- v4 C& k, X
//遍历一遍
2 A; V9 q. Y& U/ |1 X if(A*A<A[j]*A[j])
! c. o. x) O4 F! `. l5 f' u {
& X1 G! ^7 V: H2 q% l/ G$ f- W5 _ result[k--]=A[j]*A[j];+ G7 Y* y. E6 H
j--;8 S% V$ `+ L2 c6 s1 Z
}
. n0 f. b: t( W E2 \# s, {8 n. j else
4 X" Z, G. m2 O/ [ {, M# f# E* x" \: v% p: e
result[k--]=A*A;( L( e/ _# X# \+ ~" Y
i++;( T z! \- F: P
}
9 `. f3 ?) y* ?; L }
6 n! L) D% M& z return result;! H) N% g) f7 `4 b9 _) B5 x
+ B' I7 z& y q5 i7 `9 z" k
}2 l1 i5 l& [0 H
};) p; ~$ p. p* e$ ^
: h8 u$ g* S; A" s% e: a, k4.长度最小的子数组
$ K2 l% @- [. d. {) \) |! \$ y/ a* Z给定一个含有 n 个正整数的数组和一个正整数 target 。
: W/ k1 Y: H6 F4 G* z) n
7 U* L" Z# L7 ?) C5 p找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
- S/ F9 Y$ b. U: u" P; m1 S5 I; Q" D+ v9 H: @; b. k* A
方法:滑动窗口法5 a% R2 U3 s9 v% |6 x& F
" _% J# n3 N" n! I& _ s5 o* c) @0 m5 M
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
~) {+ r3 I f+ e v$ m) @) t2 Y8 r- m# c+ r) M( W E
三点重要:3 z4 i# ]4 c o1 I* E' I
$ q( }; D3 u4 R. a. E) n0 j
窗口内是什么?
, l' ]4 g4 [8 Q9 e+ Q2 V窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
6 F0 u b6 f0 p n! }如何移动窗口的起始位置?
3 s, ^" h* k v( _! h: ]窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了, ]" \/ z3 c5 o7 ]5 T, o
如何移动窗口的结束位置?
" d! ~3 l! L- A* M9 b+ y- c窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。5 G( r2 \: G- N9 }2 v7 g4 X
% y9 l" g- w- M) k% M0 u
代码如下5 ]; P, _6 H% k* M
/ W6 d! B( [* T& v: d# M
class Solution {% |# _# w% o/ i( C3 g
public:9 v8 Z! Y$ @6 t/ n
int minSubArrayLen(int s, vector<int>& nums) {
% l+ T1 E( D+ b7 i int result = INT32_MAX;
Z9 r& |6 W1 l* z/ c: I3 {) d6 L int sum = 0; // 滑动窗口数值之和 j5 p6 d* p3 d
int i = 0; // 滑动窗口起始位置
3 w, T8 i9 l4 J' r H8 e int subLength = 0; // 滑动窗口的长度1 m2 P; _- A( q( J* k
for (int j = 0; j < nums.size(); j++) {
; H' j H7 d8 N; R sum += nums[j];
+ N2 o" Q$ o( m- H" L // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
. F' h& t& v; o while (sum >= s) {, e% f9 F8 N0 d H! Z" [) t, E
subLength = (j - i + 1); // 取子序列的长度. @0 X ~* b8 ?' }/ W7 @- E( V2 v
result = result < subLength ? result : subLength;//一定会赋值* {. C: |9 Y) v
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
5 j( k6 K+ J3 ]& s2 v; P; ? }
6 X/ Q z+ `# U" [0 v$ o1 b }1 Y" W% v9 q t8 @" x* p# j9 Z
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
. a- C T8 Y2 w return result == INT32_MAX ? 0 : result;
! s% ] q" v' @* Y/ \ }) \& I! ]7 N- `3 @
};, ]. e, e# a1 ?2 U, {
3 p# |5 R8 R4 c `) d. b
一旦大于,就减去左区间的值1 u* h, M6 g0 H6 W2 q
0 y+ A9 r U) w5 e9 j% ^5.最难题螺旋矩阵||/ D; d, N' k6 v
模拟顺时针画矩阵的过程:+ q+ H% Q: _1 H+ k" S) V
- B+ s/ d4 [3 S, }
填充上行从左到右
& \0 `' U8 M, `* g填充右列从上到下
+ I8 {2 Y/ \! j7 v# }填充下行从右到左( y/ d' W% c% ~
填充左列从下到上8 ^7 a- ^$ \4 R& R
由外向内一圈一圈这么画下去。
# {9 Q- m | r' d6 B; n! }* j: i8 w; ^1 J2 S2 u+ M6 ~
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。/ m% n, k& `) M( T) ?
- Y3 z2 K; X6 E! |! X# j/ H2 T8 P/ F7 }1 \4 c
. R) K* W% P3 Q$ w1 f8 E9 b
- ^3 Y. ]$ k; C4 n7 ?9 n% a
0 W8 t! }# @2 V% ]class Solution {! a% k7 e$ f: ^; f
public:7 A- i$ _* w* D' l2 w2 y' p6 y; y
vector<vector<int>> generateMatrix(int n) {
. r' E4 T4 M# U- ^3 t vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组: a- P9 C6 Z, q" H8 H& G
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
5 s* P9 O% K! ?3 m int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
. |; P0 K( @& R p# Q* O, b. Z int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)8 C7 o, q. Q3 {% w1 p" t& L
int count = 1; // 用来给矩阵中每一个空格赋值
) |8 J) i3 x! }/ v2 E" A- G int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位9 ]* m0 f2 E4 k8 u0 |- T, Q7 q V
int i,j;8 ^( }4 v+ G# ?8 F/ t& I
while (loop --) {
' ^3 s+ k; Z% U* i% q9 w n; ]& ~ i = startx;2 E& k* X3 q4 R4 k/ {
j = starty;6 M- K' v) ^; f$ ?" X: {
2 u- x, K2 U# A/ }% s* w0 Y // 下面开始的四个for就是模拟转了一圈' V# F! D% v/ ]
// 模拟填充上行从左到右(左闭右开)
3 H, M8 a" q: H( @! p* W for (j = starty; j < n - offset; j++) {
: a6 r7 O p0 E8 a res[startx][j] = count++;6 q+ J/ y- p2 |5 @
}/ u, `9 E, o4 Z" F& ]% V0 S
// 模拟填充右列从上到下(左闭右开). e" |0 } q. c' N5 M1 a9 U
for (i = startx; i < n - offset; i++) {/ S+ u) ~5 s l4 F0 g8 o: M z( |
res[j] = count++;
k6 _9 X2 c! g" R. O( l, b7 | }9 w* p( E5 S% M5 O- b3 |
// 模拟填充下行从右到左(左闭右开), c* c0 ^1 M& |
for (; j > starty; j--) {
* t5 O$ I0 C3 h1 j, k& P. N- t1 l res[j] = count++;
& @9 B+ h) ~( G& p* X* ^ }! P* b# S# \" S# O6 @
// 模拟填充左列从下到上(左闭右开)8 }) i. Q( u! [$ p1 H1 L; Z
for (; i > startx; i--) {
$ P2 ~" E7 H( z; f res[j] = count++;
7 Z5 K- _+ {1 c }
: v3 E) x0 Y, ~" H9 o* k0 D5 B7 q, }% A9 Q
6 q3 k m+ X9 I$ a7 Q$ Y. \ // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)2 t$ `# \) y* o4 D2 G
startx++;
; @* q1 P9 n {, H4 E starty++;# y* C( a1 w3 U- `
+ T+ w, ]6 T( P1 R$ ]5 j8 C0 [9 G
// offset 控制每一圈里每一条边遍历的长度' P& q6 t) y- S' k- b
offset += 1;
5 A7 O/ m+ ?# h7 g. \ }3 ~' d/ D& v- b8 T/ v; b
9 d( B, p# [" ?1 ] // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值* n, @- Y8 W' C+ V& x+ V. u& }1 m
if (n % 2) {$ m' p3 n2 U, j7 N6 l* Y
res[mid][mid] = count;9 d9 L _0 v! X/ f, }
}- u9 F1 I" c7 j {; D' y4 K
return res;
% h8 o, c& |; s, O/ B% E2 W }
+ W& s6 }! H. i# v3 x+ v};
* q6 E7 X+ k8 h1 r: `) e; I( i4 ~: }1 G
————————————————2 B) S6 C, s, D3 K; E5 e( _2 c1 S
版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
* C/ |6 p8 q# }1 Z/ [9 ~原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039. ]0 }# U) |! j9 ^" v
3 q+ Z/ M( L7 n1 _6 @: `; A- H1 D2 x* Z) m8 i
|
zan
|