- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564695 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174631
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习
# p8 |) D# U& I' U* o4 U9 R8 D+ h1.leetcode704
" ]8 E0 e- m- c: f( j+ q给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
6 Y" l+ j8 Y, T# N( P5 W$ V# ]8 M3 z
题解:升序 数组
3 c" K* B0 W y7 d; _8 p. }5 @: y/ i9 `( M
方法: 二分法/ C; K" }: ?- Z$ s
/ t1 Q' g1 S9 N- y
思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
& c- w6 W: h0 |' A ~% U/ T$ t* b4 E3 Q1 E$ q; s8 _' W5 B/ {
比较nums[mid]和target的值:8 ^# r# W: d0 f0 _2 o& _
4 @* _6 d4 h; f3 r/ k
如果nums=target,则下标i即为要寻找的下标;
: n* S! J$ H2 D K8 t* U3 L- z) [
8 e {0 r: a4 `0 u6 g如果nums[列]> target,则target 只可能在下标i的左侧;
. I6 p4 A+ d1 Q" T5 o/ Y
) y; t9 [) e+ h3 e8 c1 I2 }. vclass Solution {
: N3 X! ~1 _/ Wpublic:! D* R. H5 H6 g' U& z
int search(vector<int>& nums, int target) {/ I, \& w$ l- g- Y+ D3 V, `
//区间[left rigth]
: p2 @. L& p, s. r2 p6 F int left=0;
1 @2 C H( V9 B; t/ K int right=nums.size()-1;& s- u9 e7 k. t& F3 M; u
//结束条件 left>rigth
( u! Y t) W) R; D" ~$ s while(left<=right)
; M, `. G' ~8 k, }/ u! t$ Y {
- y; J7 \# v! u3 i7 x int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]2 O) r' H% v% q' L( s
//[middle+1 right]
5 z0 c/ j) U5 y if(nums[middle]<target)& E8 I! C& b+ R6 G6 N6 e* c" k
{) w. i# Z" s% Y9 y6 ^2 ~" Q6 E
left=middle+1;
4 ~* i+ r5 Q- c- _" k2 \8 G! J q: r } N& ^6 z8 m& }0 m/ i& q
//[left middle-1]# j+ |% Z9 x! a8 h" K
else if(nums[middle]>target)" l" j' k; B' n0 \
{. X% S: p& p% R! y' A
right=middle-1;
* s2 L+ h* L( m8 S3 ]0 w }
, j7 n6 [8 I% J# V' z7 ~4 r else{
9 I4 g' ?' c3 r return middle;
$ q$ f. M2 c6 Y/ T, q) v ~: G }) P1 S6 Q9 n1 O- p' ]
" {+ ?5 c* F& p, [! s: I
}
; U# ? x+ Q' t$ N; n$ ? return -1;
3 H1 _" {% z* ?) c7 w9 ]: g" P( v$ T2 S* v" d( u% M$ e; @
}
6 h3 ^; a& z, N};
0 m# X. T' D# k. \2 z$ x8 p/ e! L1 y* t4 F+ M! y* G% \
注意:
+ a2 F* V. n j. w. D/ f
; p% w0 L1 j! B, i% v0 M(1)设立区间为[left, right],终止条件为left>rigth
' e4 \/ q; u+ S( x (2) (left + right)/2==int middle = left + ((right - left) / 2)7 N% }0 o: f, z' l( l
(3) 通过改变区间的左右值;复杂度logn
s& q( _& r- h
6 l: h; ?3 d4 |/ x* M5 ^/ `2.leetcode 27移除元素
- Y& K9 [% j$ w4 L) z U& X给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
! X% P! ]! u4 I$ ]; R* u% Z% _0 s( A
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
" e* S8 `7 U, S' j1 f2 d8 V' x) c: }* t/ x) r: h" _
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。3 m! n+ }: I$ I6 j! Y9 y- P5 h
/ N! z2 ^) ]# O3 k+ N: q0 D9 c2 R示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
1 X/ W0 l$ `: M5 g- [( [' d* P3 k! u9 U; C5 \+ ]+ }$ C
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。1 R7 y& }3 ]' s/ w% C2 e; I& N
4 ]' b! J- y1 @# u. X7 L
思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
2 g6 l; ^' \2 Z" D; p1 c' g1 W+ \; W
方法:双指针
% O# W1 l" n* C7 d" C% |$ J- A' ^: a2 z& s0 P
class Solution {
6 E0 H7 u4 w8 W6 {7 ppublic:$ M' N: d% c' ~
int removeElement(vector<int>& nums, int val) {' P; W3 p; ?" ^. t6 H8 ]8 t0 |
int solwIndex=0;# N9 u: ~& B! X' o
for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)9 i- I/ Z" u2 s/ F: W4 m
{2 Y* S/ U5 B3 S
if(nums[fastIndex]!=val)
, n9 Z, e5 Q: S9 q, j5 s {# {; n( \) S; I r: n* {! [
nums[solwIndex++]=nums[fastIndex];5 l# i' G: _' L8 R- g$ f
}% L+ F8 }3 Q" P& G. Y
}. ?; V9 K( ]# E
return solwIndex;
M: b) ?- N8 r! a- ^ }
9 R+ w, R7 H2 _! q/ c; U}; [1 L* K3 y3 q, N1 c, W7 T
solwindex:用来覆盖
3 }+ i t- Q# u: \0 n6 ?
- D1 O% N' n* L; {3 ofastindex:来找删除元素++
4 D {5 j1 G9 f
3 B1 g! E1 ^1 K& l9 L3.有序数组的平方( W0 s! ?9 v+ v% K0 s
给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
4 c% ?/ S" o) x$ P) t& z' p
9 H& I/ }9 h, @' g9 H0 ?+ u数组其实是有序的, 只不过负数平方之后可能成为最大数了。
) t! v5 a1 l' [! R! u6 O. ^6 Z, R5 Z7 m k# ]1 m: T
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
( b; k5 ?2 K% k0 _# m( ?5 S- e! t8 O' X; b2 S- R7 b: s5 p s
此时可以考虑双指针法了,3 x7 |+ V. e U6 r8 `
T( u+ h$ @( ]+ _8 Pi指向起始位置(负数),j指向终止位置(正数)。
1 c' z8 Q+ n" T
8 G2 |; x$ h+ \$ u1 S6 r6 r定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。/ ]6 ]8 w0 o8 \# y' F
0 S `" g* Q4 h- f5 c: D
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
4 U! S' q9 y( Q( S8 C6 F, F$ k0 {( `5 n! ]1 `- {. G7 I
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
1 {3 z5 K. w6 K* T" s
4 D% a! k# {* W, Jclass Solution {
: D! x9 |; t7 o9 l5 ~public:
( D3 |, w2 y# c vector<int> sortedSquares(vector<int>& A) {6 J4 O- _. N- w4 k. b4 M( y( c$ ~
int k=A.size()-1;- ^* G$ w1 y; n% g3 m; ~
vector<int> result(A.size(),0);, m1 N/ G7 S; Y+ r8 s+ K
for(int i=0,j=A.size()-1;i<=j;)1 l4 [! @6 ~- Q9 E4 S
{/ g4 P, j- L# O1 x, l& s
//遍历一遍
8 x: l! r: C: V; A5 D6 f if(A*A<A[j]*A[j])
$ q# M& H7 ~) L# J; t& T {
' a( Z4 m0 P9 P( Q8 W7 U result[k--]=A[j]*A[j];3 q$ i5 R/ M3 K+ X, c& F2 X
j--;, E, T2 {9 D5 Z" `# l
}$ P" g5 c2 v. V/ j
else
: \2 J. u! K$ z- \. ]1 [" v {
+ m' M/ D* U8 m: s result[k--]=A*A;7 v. G2 L/ j+ w' F
i++; E* k1 V' g/ _$ q' z& X- D _: _
}
9 x$ d7 m- Z/ G7 D, d1 c# ]. n }4 x+ H3 l+ {0 w* q
return result;
" c# k9 W3 }# R& i2 e0 T0 h( q. P7 E: U
}) f- Y' Q6 E3 r; |
};
, x& [; \# |) z% Z: e6 `* b, H' _4 K" O7 e( c9 [ b: T0 J6 ]
4.长度最小的子数组
) p) x) U1 d+ o7 Y, d1 ?- |2 }给定一个含有 n 个正整数的数组和一个正整数 target 。
- u' w) [' U: p3 N2 F3 @2 `
# e& V0 G- h) l! b7 P找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。* y7 x+ U$ W: l: |# P( }+ \
, J+ m/ U, \5 b4 Q
方法:滑动窗口法
& l$ [, {$ @& O3 b2 U# U( E3 a3 X- ~( G
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。7 g! s1 Q+ `7 ~. |/ I; @6 K
8 [- z1 F+ T% H" R) z- g. f三点重要:1 u; z' Q5 Q3 v# z: l- u7 \2 E8 r5 k
" D, P* S9 y$ d# m! O/ Z7 m窗口内是什么?8 ?+ v) X; D& a; g
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。2 O5 j! l( b1 n, O
如何移动窗口的起始位置?9 a9 @/ g- ]4 C8 U& N$ k4 D" k5 e
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了3 }- i: P a) i8 v
如何移动窗口的结束位置?
F/ g R/ l: x6 L8 U! g& W: p窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。: k+ B# }0 T2 g* T) H7 T
- w" i5 j+ \2 d2 A, a9 P c+ P 代码如下! ]( R9 G9 H p# T4 t! X/ F
/ `/ ?$ B; Q1 K2 h7 R7 L2 E
class Solution {
* s% G1 p9 w( t' X2 ]7 {public:
# m( o1 \$ h* e3 l int minSubArrayLen(int s, vector<int>& nums) {
- t t8 K6 d9 F; I, p$ O U( ~ int result = INT32_MAX;
% y3 _' V1 M7 Q( a& W2 J; ~ int sum = 0; // 滑动窗口数值之和
: V6 _3 X. \% y1 H" b int i = 0; // 滑动窗口起始位置
! `6 f! P6 ~' R% E int subLength = 0; // 滑动窗口的长度+ B6 s, G$ M! Z# S+ R5 N6 S
for (int j = 0; j < nums.size(); j++) {
! o6 @7 e; B- s$ H7 U6 h sum += nums[j];4 o5 N: G7 A9 F
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件9 s- S* c, A% u; k4 d' t
while (sum >= s) {' K9 m2 i* C+ Q1 m* Y7 R% m; G6 L
subLength = (j - i + 1); // 取子序列的长度
2 m5 r& n" X# N4 h result = result < subLength ? result : subLength;//一定会赋值
2 G, M. X' d" y sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
T$ _! H( [. \+ C; X P& ^7 U }" j0 B7 X8 @( C: l
}
8 j& a9 e( [, _ // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
; ~6 r1 N" ?/ l return result == INT32_MAX ? 0 : result;' e$ [5 Y. w. b' j1 W6 k
}
5 @. K; Q/ ^1 s};
: L& w" y& s1 L5 q: {$ H$ F _6 c) E7 o9 a
一旦大于,就减去左区间的值
8 Z6 d7 k% \/ ~; Q$ G G7 |! v3 g. g2 u$ v
5.最难题螺旋矩阵||; G' {( u( d# c
模拟顺时针画矩阵的过程:
3 Z! {3 t' s8 ^/ ~+ y
2 u6 p1 @7 n; R: p) }填充上行从左到右' M/ R" F3 Z9 G. L$ {
填充右列从上到下
6 Q: h7 X8 ^# m: Z% J0 V A填充下行从右到左
, w- O9 J3 w' `# k J/ f" P填充左列从下到上
. h& C" A* J! v; V1 Y6 t! T由外向内一圈一圈这么画下去。8 ~9 d( d; \5 G! `
8 P6 A+ Y3 ]1 ?. \( U1 K0 G
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
/ M. {, w, w8 T; V$ p$ ? ]" b4 C; O& [" Q' U4 A0 _
, T6 p, u/ j' {! T& {" O
: b: }8 A0 A" m- G' x- x/ s" t T6 M/ O
* h" t9 b4 u" n6 w4 xclass Solution {
7 w' \( t$ x6 _4 S$ e( R' V4 Npublic:
, Q4 z9 \4 p3 M, W! ~3 @$ f, W) ` vector<vector<int>> generateMatrix(int n) {3 p0 E0 e8 H4 N
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
" \* m9 P$ A0 Y7 n- r- P$ _& w int startx = 0, starty = 0; // 定义每循环一个圈的起始位置& V. b- i! i* Q8 o0 D* v8 |
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
1 O, y* D" G5 o1 k int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)" o, y0 ]4 T# x& d; B! q' i9 G- n
int count = 1; // 用来给矩阵中每一个空格赋值' D3 M8 I2 e7 m( d" w6 b
int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
+ Y& f1 @1 E+ ]* i int i,j;
- l4 }/ m% p5 y W, {3 g while (loop --) {
) R7 U5 c* W2 K- X$ d# O3 C ` i = startx;
' d/ W. C l& {9 M: ]/ A/ v4 q j = starty;
2 C' z% \8 Q& e9 `
) d( \6 Q0 J- R/ e* i' s: D // 下面开始的四个for就是模拟转了一圈. P4 z/ \0 |2 v" v' B) G7 M3 x
// 模拟填充上行从左到右(左闭右开)6 x; g- h: D. S B( N S O
for (j = starty; j < n - offset; j++) {5 n" n' H- s! U( j# \
res[startx][j] = count++;
5 r6 A+ O9 u$ v) h. @9 ]: P; ?+ s; d }$ Z6 m" Q- P! D( I6 ~! E
// 模拟填充右列从上到下(左闭右开)
$ f" Q# ]7 |5 u" ~$ y for (i = startx; i < n - offset; i++) {! V" ]- n3 |) k# i# w
res[j] = count++;8 ~# o7 r( ^2 Q/ d4 @7 d: n
}" h9 C8 U8 ?+ V
// 模拟填充下行从右到左(左闭右开)4 O* I G# _+ N6 e
for (; j > starty; j--) {8 C4 Y! y6 H2 D' z3 u5 a. P+ ^
res[j] = count++;
0 C2 f l I/ p }; X4 e$ s1 |( N( Q
// 模拟填充左列从下到上(左闭右开)
; S& P! e$ N- p7 d& v9 m, Q for (; i > startx; i--) {
. {' A) ?$ j( i, ]# h8 e% Z0 L res[j] = count++;1 [5 }# \$ B0 i
}
T2 C3 |( z% ?* U
' J3 P0 n5 D9 N6 } // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)0 N" ]0 x" t/ I( V
startx++;
$ K7 E: \4 k0 I; d) M# }+ D starty++;( s4 r7 E. r5 S" z9 z
! n- `- |4 y2 ?. y& `
// offset 控制每一圈里每一条边遍历的长度! B2 l$ }+ ], d; {: @ P" m
offset += 1;
; V8 v" y ~5 c4 z6 g9 k# [: P J } e8 Z8 b4 v, p4 P) p: X9 L
/ m# {, l3 W/ [5 e6 A! m; i, _" x# K
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值+ M8 R4 y, h# I
if (n % 2) {2 @9 Y: u9 \1 R% c. d l- O: F% J
res[mid][mid] = count;
/ k8 s1 h8 b) p8 Q' s }
. f! s" @& f# g( V return res;2 O6 D0 V7 D1 ]6 d
}
5 ~7 \' t; T& [5 U* C};+ n% c" X, E8 g% a& o
! K& ]. s2 P& ~' e+ f& \$ \% B
————————————————
! X4 f8 w/ I* H" e; `版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。0 @1 ~" ]& E9 L" ^0 q3 z6 O
原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
$ w' c; Z) z o6 g+ Q1 v
3 `+ s- h+ }( |. F- {6 M" C2 S; k$ Z+ x
|
zan
|