- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 567259 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175401
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习" j, z3 D+ M. |. E; S4 e( M
1.leetcode704
- {% B0 I+ @, c* d给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。; I! y0 l: o/ O2 ?+ U2 [+ Q
# I2 Q; |1 A, b/ M$ {4 H- J题解:升序 数组: |" M* Z9 J" X% B" h
- ?5 Z' V$ U6 V方法: 二分法
+ }' F4 m2 A2 t% _: `/ G" ^/ A( S+ c5 |* N$ K: b+ |4 u5 J/ J
思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
0 o0 K1 u0 S# e6 ?
8 ^3 ]6 N7 O. {( ~4 b6 ]% {- K9 h比较nums[mid]和target的值:$ u2 Y& H. [6 ^2 v8 N, c
: B9 M7 I) m" R( h6 K
如果nums=target,则下标i即为要寻找的下标;
. z {- ^% X- {3 J) D: P* V7 M+ \- g) H9 |3 I; m! h
如果nums[列]> target,则target 只可能在下标i的左侧;
! f9 t/ B- J! K D) d" Q
0 F) x& t2 S) m4 ~$ C. rclass Solution {
9 W- r, K/ B7 ~0 v3 e/ D# Zpublic:6 ?' F, D1 C R6 ?, [- U0 P* t
int search(vector<int>& nums, int target) {, Z6 q' }" e$ |' i0 O# L
//区间[left rigth]- ~6 b5 n/ N" |! \
int left=0;, D" @ a2 G- Q- T/ M% s1 l
int right=nums.size()-1;+ v" ~, Q6 N8 K I& |+ E( x
//结束条件 left>rigth
; g1 P2 l" r5 K4 d5 y- @6 |5 m while(left<=right)8 d8 [& E9 @ q6 Y( o r
{* y& j6 z' R, v
int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
9 L' R4 |, y5 i' B //[middle+1 right]# A" E N$ e+ i. [
if(nums[middle]<target)
* y! G {: g$ R6 g+ g0 t( ^1 _. \- n {
% E0 o9 Y5 D! { Y left=middle+1;
5 u- M# r% U- H7 K9 t+ T }
) V( O- o7 H6 N4 K4 \ //[left middle-1]
' C5 o8 ~) ^/ R- U8 f* Y% X2 ~/ q# E else if(nums[middle]>target)
8 {5 q4 u; J# [9 m( u$ X {( v% D% T% b( D& }
right=middle-1;
7 m) B. R9 }; |$ A/ @6 R' Y- W. z8 h }2 \* L G) k; H, V" j ?
else{3 W1 ]( s1 o1 }; b
return middle;
& k4 o4 ~& P7 B% }- i' ] }$ P: T i, o, k; g
! q* w3 \2 i& A2 S, A# F# z; M
}5 ?, ~: `+ u6 Z" z5 s" p
return -1;' L$ Z P6 K+ [# _
& P, q: G2 q7 m( v
}
3 J- z. I7 M# z0 ]# w ?9 ?3 z};
7 C W r( a* U& K3 d+ f& _% A
' b: Y+ g' H; Q5 r7 @0 R( N注意:' D+ y3 w0 u# [" d# n: W
3 p# o2 ?5 d, q5 k, Y3 p b& N C
(1)设立区间为[left, right],终止条件为left>rigth
8 Z' U. v$ [9 Z- p, d( G+ [ (2) (left + right)/2==int middle = left + ((right - left) / 2)
* x5 t. L# \. \' n; _/ h# L6 M (3) 通过改变区间的左右值;复杂度logn4 r$ E x( J7 {- w
& {0 s8 ]; s) Q! j
2.leetcode 27移除元素
" e* o8 P- `; C' n0 G' n给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
2 z& _8 V7 S+ R8 V y+ H
- [! g. I0 `- T; r7 q2 h: d不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。5 Z# w. l9 K6 l. A4 S1 t* ~- J- Y
' E) y) L$ ]" x% ?' z! O8 j元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
, d/ `" Q! F% g9 S) j+ @1 c" b( _( {; F
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
4 d0 I2 B% B7 ]( Y7 m, l+ V4 _; m6 n% _# T, V2 H
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
- {8 c7 }/ t* P8 I4 Q. Z5 L+ k7 R. ^' |3 Y/ B% I
思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
$ F; e: _# Y) x& l9 b. F2 X# g" q1 C% _, w: f I9 `) G
方法:双指针
+ C$ |6 h! @* {0 Q4 ?3 C5 N4 Y8 J9 C8 j4 `; [
class Solution {2 G. Q! y7 S, U8 y# {. {3 C4 \
public:
2 S$ f. I% J% x9 x6 V0 }0 n int removeElement(vector<int>& nums, int val) {1 m& ?" y" H- E$ _9 ]
int solwIndex=0;1 a! r8 {5 \; L1 H
for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
f8 m2 p; e% y7 {$ Y {0 u3 K; u8 U+ y& v8 h4 x
if(nums[fastIndex]!=val)
F3 h4 P g) X, ]& E1 N {
; o! {! z0 A f' m+ X1 I& @' n, _ nums[solwIndex++]=nums[fastIndex];
$ o: L* Q2 r4 h: `, Y1 q }
4 N: `3 R$ e7 o" u. K- y }" A$ g# m* E* n8 w3 N; ?
return solwIndex;- C+ R0 K3 E t/ d: Z; F
}& z- \" x0 P, c/ J* v1 m
};
% H& d. S1 }. P4 hsolwindex:用来覆盖
' p; _) w# M2 c X8 @
w) _* U7 V7 Q/ E* f, G3 T1 Q4 Sfastindex:来找删除元素++2 b4 V% ~$ {2 Y' ] e
& F; A' v, Z- o% ]9 X
3.有序数组的平方
. ]* M/ P( N, I" L2 Y给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。5 N/ d! d1 n# R7 M6 j
2 \/ u; h& ^# G& E) p
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
2 z+ I N) ]6 \: X _* t) u& O7 @
1 R% x8 ]' I) b" Q" E: d" L" x: ^8 `那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。: r8 t3 ~' H. i" A
, K: \. `2 d6 [# P) n3 T# a此时可以考虑双指针法了,
6 `5 m3 x3 N, r5 K7 I2 N# ?; U8 p2 \4 V7 C4 W6 [( B3 Y
i指向起始位置(负数),j指向终止位置(正数)。
7 ~3 H+ C9 M8 w' q
( b$ Z6 e% e/ b7 S: t- z定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。: }4 z" e. y4 \5 b- @
) z! |4 G8 q9 U2 d. ~% x
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
, {) o" Q2 ?4 B, Y2 K5 d$ L
! g+ }; z; @$ r6 [8 c: t, ?, K9 K如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
& M; |6 U9 t4 M" B" Y9 ]1 S! V
* l; f, H% j( r, c, i+ wclass Solution {
& C& }1 j+ @! G/ ?5 ~public:( q! D6 N% @7 m" z
vector<int> sortedSquares(vector<int>& A) {" C. _5 k$ d: x
int k=A.size()-1;
- L5 y+ }9 n' @& Z+ `' m vector<int> result(A.size(),0);$ H% z( ?: @1 O" ~$ X1 a
for(int i=0,j=A.size()-1;i<=j;)
2 V) ^+ Y* f! j$ r! P3 ^6 [ {
+ E- n, C( C' `9 x( p& r5 Q( _7 e/ [ //遍历一遍! x/ m, S( N* f
if(A*A<A[j]*A[j])" X6 N9 f8 p( ~3 f
{( n1 f% I3 _, W. |' c! P
result[k--]=A[j]*A[j];
* @; e, x" U9 q/ g7 t j--;' t; M3 f) S, {( _" a! @
}. p: _9 g7 Y3 e
else
0 }' u/ V* @; S& {- R {/ o+ {7 K) t- B! W" o6 u
result[k--]=A*A;8 ^3 I* f2 R' h* H+ j
i++;& ]* ~$ y* A# d) j1 m3 T( \
}3 ?- }$ S/ A: a& Q& J" i9 r! V
}( F; L. P5 S Z [# d
return result;1 d. L* \' V. B6 N2 Z0 T, E
# [+ u! y: }/ [) U }: f0 x! D U! Y* @' e9 \
};9 _- q( V2 X7 q$ |' n) H5 h
& J; Y4 e' ~5 V1 o4.长度最小的子数组; C+ F) L+ F/ `1 L2 {
给定一个含有 n 个正整数的数组和一个正整数 target 。
5 n6 Z4 f$ K& n L, t, [# A8 \' R0 |8 {" V
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。2 I5 T: D5 L3 x; l' q8 T/ v+ J
+ w `; S# F* x6 a0 x" U8 p6 v
方法:滑动窗口法
- E: Z0 c* I8 q/ }( ^7 A: f8 i
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。( D% u3 k9 U7 R
6 w* D8 {: h7 p7 t3 B三点重要:
( E0 I Z8 ?& W+ z; f% r) a# b7 l1 D
窗口内是什么?8 Y# ?; `1 c( q: S+ ~
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。$ P, h9 H# W, H# W% o2 e
如何移动窗口的起始位置?
) K7 m4 K s/ o/ t* s6 G窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
# J9 L% ^) y4 o" I4 y; `% x0 ?" S2 o* w如何移动窗口的结束位置?5 _) K" s0 t2 m8 ]. Y
窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
) R4 ]' v) u2 c: m- P, p" C; s
: q% J2 T( }; U- D- V& D) ] 代码如下
. t, N; d- W9 o. I5 z/ i; }% b3 H( b! s$ d: b
class Solution {
2 o* N' k3 X% ^/ _+ K& K4 \public:% \+ h0 d* w) X+ m1 {0 F
int minSubArrayLen(int s, vector<int>& nums) {# q+ U. _3 s2 A
int result = INT32_MAX;' Y( Z% X7 M) ?
int sum = 0; // 滑动窗口数值之和
) T5 o( ?' F- f H9 Z* w; w9 w int i = 0; // 滑动窗口起始位置8 Z, d1 d7 [3 y1 t9 G
int subLength = 0; // 滑动窗口的长度: i( Q# z2 F* z7 @
for (int j = 0; j < nums.size(); j++) {# O+ Z- T/ p# o( v) m
sum += nums[j];
' j% H# h- J6 L* _. K // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
" d L0 U8 }& o$ O |6 `3 H* @/ ~ while (sum >= s) {" F1 Z+ [' d; E# h" |- t
subLength = (j - i + 1); // 取子序列的长度
% h. }0 N) ?: A5 A, x, x result = result < subLength ? result : subLength;//一定会赋值
' d# U( _" p( [. ]- X( N sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
J( q. o/ v9 g0 X) x }) s. K6 r- g. ]6 G8 ^) H
}; D0 Q3 {5 p. ^
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列& L6 ]0 \' [+ Q9 k& x
return result == INT32_MAX ? 0 : result;& ^! I9 B) }9 Z/ f w
}
* w8 E: J C0 [) ~};. k$ Q% H+ u% C$ S2 t% t% d
' I9 A7 _- b1 A- W一旦大于,就减去左区间的值3 q) f+ ?2 C9 i1 b2 o i' l/ v1 m
o7 ^: i2 B8 x
5.最难题螺旋矩阵||
! ]. H% d+ O" S! Y% c5 D模拟顺时针画矩阵的过程:
) n* u, U# ~ x V# P$ E J! a$ d* `( f( Y2 Q
填充上行从左到右6 [" Y( F% p/ S. W
填充右列从上到下
9 ^* ~# ?3 f5 l0 {/ E填充下行从右到左
& A' q7 e' S4 q, c2 f" k填充左列从下到上
8 F9 r7 K* p" n! u3 h& U由外向内一圈一圈这么画下去。
; _5 T- F, j- H3 Z' z" X8 X* ?
# B' X+ `+ t3 w/ O' \1 i这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。# S# i% y4 I* v% W
% m/ c) f$ B- s; c2 m6 t
- I+ `: q* i1 v7 y$ S7 n; j5 [" z
0 y1 E7 R; D6 P4 Y* o: {' i7 I' | g% e0 q! z
% [; h/ w1 l: M0 ?. L
class Solution {
2 {2 K0 A Q. r" apublic:
; ?0 {& r/ C5 i O. N; ]/ S5 b vector<vector<int>> generateMatrix(int n) {
. |& S. V. |( W+ O vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组9 e, z: E4 H" n/ }5 N( U- f
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
5 E. e2 A0 \+ a) F% d$ N int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理$ j8 T/ j( I$ F& Z1 p& ^2 Z
int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)7 ?$ m+ p) F! k0 x1 p' T
int count = 1; // 用来给矩阵中每一个空格赋值
; k! r% i! u$ r, M! q int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位0 I2 `, e+ c/ M- L% ?, V+ C: Y
int i,j;( P2 j, g3 Y* F6 Z" E
while (loop --) {
4 @ R9 m' q* X+ @& [8 e4 w' l: E i = startx;
! u% C0 J( e6 J1 W, j& j5 }7 g j = starty;4 V1 Y1 d& b* w+ n- C/ k- y
( L2 O$ k! p" C' W // 下面开始的四个for就是模拟转了一圈. h2 m* j% P- q0 l, u7 J" @$ X
// 模拟填充上行从左到右(左闭右开)
, _" C* H. l& [* m: T for (j = starty; j < n - offset; j++) {
. u6 H3 O Y) N' | res[startx][j] = count++;/ J8 ^7 c% t$ ?
}
, B( B- v- ^ {( t8 G // 模拟填充右列从上到下(左闭右开)2 q4 F- R5 G7 h8 n7 q+ J, H' m; c
for (i = startx; i < n - offset; i++) {
: n' I* P5 z% S( |. I res[j] = count++;
4 w1 r( @+ _& A3 Y2 A% v }& r- u* L$ b) K ?- s
// 模拟填充下行从右到左(左闭右开)" ]9 ]4 W0 q, X* V
for (; j > starty; j--) {, n7 a) m `9 e4 i7 ]: m {
res[j] = count++;
* y9 W! E# h; [, A7 j }
3 j- `5 P$ r: \9 P4 g+ B' _ // 模拟填充左列从下到上(左闭右开). P5 l2 j6 U$ E% z+ K
for (; i > startx; i--) {7 y; ]4 D# {7 @& [5 | e( ?0 p( ~* ^
res[j] = count++;
2 `" ?" S4 q8 ?' A0 Q5 b9 u1 } }% e$ d8 y' C( w/ L. b
8 v/ W: _8 N8 i4 r6 e- x
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
. F# e( z+ c$ }' ^) J startx++;) l6 M# o# I" x3 z8 E
starty++;
% Z. [" T0 y8 c: U4 t- I# ~- Q/ D! x# z3 M7 e
// offset 控制每一圈里每一条边遍历的长度
5 P5 w3 R4 U( v( P9 P' ?( b. \% x offset += 1;! n7 ^: Y% G1 I: F2 Q
}
3 S: n- w E7 w5 g. C, k V
- @, z5 M5 y0 t" t4 z // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
* _ j2 f, t7 j& \' k if (n % 2) {
/ a9 l0 S* [3 j$ U$ N- d: P+ E res[mid][mid] = count;
: B7 i) p- u% h4 G/ s% j }
# e3 n' Y6 E* b/ C) _0 f return res;
' O" P8 c, n. U }' _0 f/ k7 `; V- g4 k2 K" C- p$ T
};
5 ?8 [, x6 q9 n! V3 x; K4 G; p) e/ y5 Y; O& ~
————————————————
7 a$ }3 k( n8 o- Y+ \7 H9 @2 p版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。9 C$ f3 r' r& b/ B" _
原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450396 W# V1 H4 o$ `
1 I" i7 O" g5 j
. O# |% A F# N |
zan
|