- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564482 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174567
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习
4 C5 A$ m, F+ }6 ^; C1.leetcode704# m' G1 P: d+ c% N
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。" B% ?8 W0 j" Q
2 }+ I3 Z. R7 X
题解:升序 数组
9 s/ [2 \7 h( k% |9 K# T/ i( E& \ P) A& {
方法: 二分法; b* U4 V3 y9 t/ O: q
. k6 w7 ~# l, ^# U9 C5 w2 T
思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)1 a* T% R4 a' P% u% Y
; O1 n4 L+ Q% q v' w) h+ K! j比较nums[mid]和target的值:/ F, X3 a$ n" T8 y& O
4 ]4 E K1 ?/ r如果nums=target,则下标i即为要寻找的下标;
" W: B5 H4 m/ U- v4 ^+ u4 n0 H$ k. }% J6 `0 a
如果nums[列]> target,则target 只可能在下标i的左侧;
) w. i1 ~2 @' H& b4 h% C
- Y* S7 ^' N E) x! w5 g2 s1 Pclass Solution {) I. g% Y: p$ \3 |# ]3 m& Q7 [
public:
& ^5 b; q9 i0 t. |2 C6 p. r int search(vector<int>& nums, int target) {* W6 h9 z/ k+ l. X ]0 p
//区间[left rigth]
: f: U9 M& O1 j# t int left=0;
! e& o* { ^" Y' a0 F2 S int right=nums.size()-1;
" I5 ] Q+ u0 C" B9 ] //结束条件 left>rigth3 w) b9 T: S7 B6 M" R: Q; e0 s7 ?
while(left<=right): D" x+ X4 W6 @
{
1 `1 v: j* t8 d0 k int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
; P5 G. v9 {" D3 t/ F$ s //[middle+1 right]% J& b# b! J" w- a
if(nums[middle]<target)7 [3 A S% W+ N$ @5 ]
{& {3 p& C# h" H# i4 `# E' x: L
left=middle+1;9 y1 w; z2 m" B
}
( K3 s+ K$ S* `- x0 h1 }* n' R //[left middle-1]5 H" ~8 ~0 x" t: c
else if(nums[middle]>target)
: ~" h* a% M+ D3 B) c/ x {! l) j1 ~. N+ y. T. V
right=middle-1;
0 G1 f k$ f1 _0 h1 _: I }
5 x: k8 ~: t. p4 P else{7 v# U& o% g# F( ?6 O$ j
return middle;
# w2 |# D% O z: W }
. K* e* b ]( N6 h' ~7 |9 F# U- F( m A0 X( m) X! J! B, R
}
6 c- S" d3 }+ _, O R, v; ^ return -1;' P8 N. k7 s0 T7 d+ O
# W" e: t* H$ ~# w5 U } y; k. S, s1 s% v+ @
};
6 L* O, R( Q+ c% e6 ^0 U) i! ?7 m2 V% B9 p0 e6 I0 h1 `- Q; Q
注意:
+ J& ]3 B9 K. _9 C- m0 G1 ~4 d& y/ ^' p
(1)设立区间为[left, right],终止条件为left>rigth0 s: L* z8 o, M# }
(2) (left + right)/2==int middle = left + ((right - left) / 2)2 K% }; k; M+ V% h. t+ C8 ]7 ]. X, R
(3) 通过改变区间的左右值;复杂度logn
5 O! c8 i! h/ Q& K ?3 a* B
5 D0 ]2 R c, u8 u4 O2.leetcode 27移除元素
2 K% X0 ]9 ?' c' O给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
- Q2 M9 d' F: j9 O- r1 I8 ^7 {3 C0 C; D/ m( k% Y3 ~
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
; t" G* n1 q; M2 `3 O: s" n. Y$ y' U* b
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
$ x; C1 D5 m8 T3 n/ m' A
+ W$ [5 b* X& Q5 K示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
% V1 R; D3 v) f1 b# a* L% l/ Z, ?' q
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
7 E$ L9 j9 s0 y V- b4 k% g5 s a+ @- G
思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。; }- w* }6 t1 O" _6 }4 B" F* g
' u3 h3 _6 h, S3 d% @& L( H2 J. C方法:双指针# X$ v5 G4 ] t+ R- }
2 k+ P6 V2 Q0 ~class Solution {
0 t! n6 T, z& b8 Q i* Kpublic:- b; s1 H! C$ i$ \1 T' r
int removeElement(vector<int>& nums, int val) {
. G! B# `( T ]% Z h3 @, w% ?) P int solwIndex=0;
; O, m$ b* D* ~ for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)
5 L- g' ] m* w3 `, @, m3 j4 v {; [; l8 k* D9 I) G
if(nums[fastIndex]!=val)5 e( S! q) Z! j j! A" U. i8 t- v
{0 S5 T6 n7 j7 ?* T1 R
nums[solwIndex++]=nums[fastIndex];
& A% ]3 Q# v( r2 E0 \ }9 D$ Z' X) ?# b, K. l E4 u
}
+ a1 R: V, d2 W return solwIndex;
; B! F( P3 S' K5 a }' Z2 N7 A. W) z% \7 V: s& ~( g
};8 @9 w- C) m1 |% `
solwindex:用来覆盖
7 X2 y' v5 g5 z4 c5 f1 v" C) e# l% l7 {' {9 `, Y8 Q1 V6 G* f( j0 O
fastindex:来找删除元素++7 G& k- O2 S v$ Y
4 m4 l: P2 z+ G% e5 C: x
3.有序数组的平方
; Z) M7 C) }% G! b }给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。% ?8 W+ ^) E5 n- m( L% @- c
; [- u. Y1 ]9 { W2 P# q7 x
数组其实是有序的, 只不过负数平方之后可能成为最大数了。4 x* m7 h$ S6 Y# _0 R
* q+ O- \# X* a0 ]1 k. S
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。. P/ t2 w7 y+ i2 w
. O& n! I/ C% a2 U3 g4 j此时可以考虑双指针法了,
5 U% O& ^9 Y1 t" f) J* W
; K3 H5 s3 R2 Y z) F0 di指向起始位置(负数),j指向终止位置(正数)。
2 G4 x2 b2 e1 n+ o( G7 P8 t& q2 J3 o6 K! o: B2 T
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。, M7 t4 n0 G& ~. e( ^& M" Y" K
$ Z- X) ]5 H! O4 Z* M
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
% D$ Y. J) E) W( l5 x$ N
5 b/ x+ w) P6 `3 x如果A * A >= A[j] * A[j] 那么result[k--] = A * A;6 s. T' ]% O+ I8 ~5 q% X% N! _: \
4 D9 ^4 l+ k! D& e6 v
class Solution {
! j0 {9 r ?" y' Opublic:$ V" x8 V4 ^ e% M* f$ S+ I9 l: v
vector<int> sortedSquares(vector<int>& A) {
1 }; k, k6 `( O int k=A.size()-1;) L* O7 x& D3 d1 ]8 w
vector<int> result(A.size(),0);/ W$ f: v S5 w1 q3 ?% E; B
for(int i=0,j=A.size()-1;i<=j;)
( U: p$ z; B, w8 H. Q2 p {
, J# m" m! J! P% D) l //遍历一遍' U1 G9 S4 p5 L" p* j0 p
if(A*A<A[j]*A[j])
# \ A1 H* Q! y# K( {& x {
! D8 b; A9 d& j0 W3 s- G result[k--]=A[j]*A[j];( n1 Y, N& Q* g* q9 L2 i; b2 |
j--;
. X0 W* W5 Q) j+ D0 L: [3 \ }
T* k- E5 q) R; ] m else" Q, B2 v8 |# l" s' W! v. o
{
& X4 ~# ]7 M- C5 D1 _2 Q$ ? result[k--]=A*A;3 N. E. \ f1 B3 M9 D2 a
i++;" g4 F4 s9 C$ ~% f! G( X: R1 i% ]
}
, H4 {- B$ c/ p' T; ~9 y }4 B. i3 K# P1 O; w- [4 t
return result;; s: d9 t& l% W) x( n# z/ p
* o; ]+ k! x& s0 K- U
}
+ y/ X* V g8 W};7 I' V" s$ D( d* r0 n( b3 G* q4 d
0 X" c: A+ {: i
4.长度最小的子数组
) R1 N' t3 ]# u! _1 I" q/ o给定一个含有 n 个正整数的数组和一个正整数 target 。
2 A# e' a9 N9 R* z! T- j3 N4 u/ D! V/ z
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。3 l2 |& ?; d5 X; b- J) {& G
) g) {4 q; m/ A9 D方法:滑动窗口法
: a+ W+ I; A6 V0 F( {% W0 S3 g
! n$ S y3 Q5 G* b; B就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
2 }! u8 h. {0 X- Z" R( k8 v0 R# N/ }
三点重要:3 i1 ?; B, _* \$ j, U
b) b" B4 E: A- |窗口内是什么?. F8 ^! y4 w& T2 K
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
9 A/ l/ Z% h& b% C如何移动窗口的起始位置?
$ C6 j$ S+ i9 l窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了2 Z8 W( d, s) H/ c3 n6 i& b
如何移动窗口的结束位置?
1 o/ J0 m5 f2 P6 ?窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
0 k8 t! F* a# |# O2 J' i0 _
' @# [0 |& U. z+ F7 {5 n [7 q4 o 代码如下
+ j9 {' e* r$ s
7 n9 B8 W* }' E+ L' H9 d5 kclass Solution {* n% m9 m U* x+ A, ]
public:8 M& J2 K, l) T4 j+ k4 w2 N
int minSubArrayLen(int s, vector<int>& nums) {
% U( x% Y* M# L int result = INT32_MAX;: N2 X8 K- H; l0 a* ` r
int sum = 0; // 滑动窗口数值之和
& {' m2 l3 @; v( I" r int i = 0; // 滑动窗口起始位置
" i' X4 Y) B/ ^" {7 q6 ?7 m int subLength = 0; // 滑动窗口的长度
5 g+ f/ B G2 y& @ for (int j = 0; j < nums.size(); j++) {
0 \+ e0 D+ C- q( E, i sum += nums[j];
1 e+ N/ O: d- G* R' J // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件% \; L4 h7 o9 S/ n F& B4 O7 m: Q8 o
while (sum >= s) {* g4 ]6 U( Y t% K* a
subLength = (j - i + 1); // 取子序列的长度
, t2 K9 U/ U* {6 ?! T* e result = result < subLength ? result : subLength;//一定会赋值
+ _7 A/ Z# c) U. ~; H sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
8 J; N$ Q. O1 I8 p4 ? }' L0 t4 S4 W' C+ `( L" Y }& u
}
) @3 E+ X( o: D5 `& C) h // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列/ B; w5 z Y# W, j
return result == INT32_MAX ? 0 : result;- B0 W" A9 f8 H, _9 \
}5 H9 \6 ^ B/ n) _7 N
};
1 N8 e. }* H6 d% \' k
% @5 c$ x5 I- {, V一旦大于,就减去左区间的值
' ]8 n' U9 S( N1 J* o% d: X
f* n- @" D0 B1 W8 }% U' u5.最难题螺旋矩阵||
- a* e) _1 ~- {+ i5 @模拟顺时针画矩阵的过程:
9 n9 n5 D' I1 O% R$ L* A' O* z5 e) [5 v" h" B- |5 ?2 y
填充上行从左到右3 Y2 }) H) O1 a) K
填充右列从上到下
& h* \) A. d! y' |填充下行从右到左
! n* p" f" g2 `. [6 F6 X/ Q( m* V/ z' |填充左列从下到上; A0 I1 {! h! ~+ C; r
由外向内一圈一圈这么画下去。$ F$ a9 ^& T9 }/ J$ M
, ] o' Y: h$ @5 G1 B这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。0 j! y! [& }8 i" m6 H
/ v% q8 N, Z0 T5 h) A
" L6 ]' j1 ^$ j: q: G; f# b$ q2 E$ z, G1 u+ F6 H- [+ M- }( O3 |
+ Z3 g/ {7 F. R6 H, O' D/ N/ g
& ]" r- A( S* U$ K$ G* x9 }
class Solution {- W. C, }# ~ N6 m" O
public:1 p; n+ H! U& Q3 @, B
vector<vector<int>> generateMatrix(int n) {5 n- M( W. B6 i! y M
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
3 X( [/ o8 I% f9 ? int startx = 0, starty = 0; // 定义每循环一个圈的起始位置: {$ y* V3 @9 o1 W+ u* q% Q6 g
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
7 g q' @5 r& s+ h int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)6 Q g$ Y9 ]. g' E' d- U2 _
int count = 1; // 用来给矩阵中每一个空格赋值
! p5 a! o# F) J int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位, `: H: X r6 y% M
int i,j;
( {# x# c1 V* r( h |) ~7 ~& F while (loop --) { a T/ O" Y; H1 ^
i = startx;
2 U4 b, w2 Y$ R& _% O- v9 i j = starty;
8 G' ]! c8 d1 g& n7 E
. ~4 k$ S' O7 G // 下面开始的四个for就是模拟转了一圈- O( P' v) b9 g* g/ l
// 模拟填充上行从左到右(左闭右开)
% F: v: V: l$ V$ N4 ?# Q for (j = starty; j < n - offset; j++) {% {! R* i. T7 H
res[startx][j] = count++;
9 V2 \! e+ g! R" {* T! L }
9 Q0 t, m, i) L/ L- _" y5 b // 模拟填充右列从上到下(左闭右开)
2 e( @4 | O/ O8 a) z% R# k+ w for (i = startx; i < n - offset; i++) {" R! t$ @ i) a7 a% y
res[j] = count++;
0 k2 ?3 _- B* o4 H' I }
/ S) N; H9 A8 w9 D7 ~2 [& f // 模拟填充下行从右到左(左闭右开)
$ _& D9 |6 Z% g- z8 U" Z for (; j > starty; j--) {
" }, C% n7 n; M8 Q' Q, H* H res[j] = count++;. z3 h' K7 B& T' \9 p9 K k# Z
}
1 w- E1 K/ m5 a$ }$ P3 ~0 y6 h/ p // 模拟填充左列从下到上(左闭右开) h* m) L! U( U
for (; i > startx; i--) {) z. g+ d9 ]; g
res[j] = count++;2 i/ P0 Q( S$ B1 a+ |* M' F
}! m+ y) Q+ J) N: G; e" B1 n
% l# O# {* u) V3 e% ^ // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
0 A! l& X) | R' J2 V, K0 R( Z startx++;
* n2 ^3 j$ _' ~+ c1 x& i starty++;' b7 r( y/ `2 @% p! c' E; X8 z$ Y
) l D3 B/ a) g3 Y: g( I // offset 控制每一圈里每一条边遍历的长度' }) s/ c$ a- d3 P7 S( M b
offset += 1;9 `6 h( S. |6 e6 S0 i+ }
}+ i7 w% V# x$ ~ s1 P7 N
) e% G- O- J$ G' m( y // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
) C; D- n% ? @6 M5 ^! g if (n % 2) {
, w: C, J1 f. N" y; t res[mid][mid] = count;
7 y6 C( T. ^. U' o$ P }* k) m" ?% ~, i5 o" w
return res;4 ^& Y' b3 Z& _# A! n) s
}9 l$ L0 L# d0 d
};
6 T* n% m u" H. N9 K. `( {# @# p1 d# q5 V2 g
————————————————3 C) y2 e/ U+ m; V$ a3 s1 @6 u- U
版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
' Q( W7 G/ J( v! v: Q& a$ v原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
6 C2 O5 \- y3 f `3 B
+ s, R. z1 L+ @
7 ^8 r0 H) t( j |
zan
|