- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563356 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174230
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习
; D8 L+ F M, ?4 c1.leetcode704, P$ `# c5 u' G( P
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。8 f, O# a6 _8 v* T& t. }, r9 w
) Q2 o3 k5 x |: _3 R. E
题解:升序 数组
2 |- v$ v& K: s' i5 X/ m5 A+ t3 Y: g) D
方法: 二分法
. F0 o* c) Z* D$ N; |% r, r; Q6 L& U3 t/ ^# M+ D' y
思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
" Q6 A3 o7 n4 m0 C6 E! S3 r# ?
3 Z' u2 B0 @% G. @) }( ^6 O8 y/ z J比较nums[mid]和target的值:' _( ]$ |4 h* ?/ n% H6 r. M
8 b5 Q' Q/ L" U' _7 k$ H如果nums=target,则下标i即为要寻找的下标;5 F$ I' ?; a9 ?' E3 i4 D. O% o& K
/ A; k- S$ _' b: D
如果nums[列]> target,则target 只可能在下标i的左侧;
" y+ _ f3 O' l# |% _# l- S4 b( Z" _+ r* J0 u0 X5 ~
class Solution {
' E/ _8 x/ r$ J9 h% q5 A7 c2 E1 Dpublic:
7 l& F; s( s! _/ }( _. {8 A( f int search(vector<int>& nums, int target) {
0 N7 Z2 j/ V% Q+ l5 H3 n. W //区间[left rigth]% Z) y. V. k3 _# }
int left=0;+ q R% L/ o! H. w" h. E
int right=nums.size()-1;4 m) Q% }- {7 L
//结束条件 left>rigth# x0 ?: a. U d8 M: r
while(left<=right): ]- v6 R; Z& V6 G6 I- k
{# ?$ q. \% T; K D) V0 o% N
int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
: g& w4 ?- x4 M. V m //[middle+1 right]
0 w* F0 L0 r% m* g if(nums[middle]<target)" q5 l6 H. G. [
{* f8 d6 _+ [7 q$ C
left=middle+1;7 w4 o5 s2 R: V: X
}' Y$ ^; O: S# J
//[left middle-1]0 @2 l' s+ k& ~
else if(nums[middle]>target)- G# @5 H3 g' V9 \
{$ R1 o, [4 K Z; }$ D3 A# @
right=middle-1;8 F) I4 c4 e% H( y8 z/ G
}, R& u# g, s! f, R5 ^: L
else{
G) h0 f( D! D; p5 L5 z9 k. r return middle;
3 N$ a" f( F& K' ^4 s: ~( K }
( ]( Y% w M4 ]; B3 | w1 g
% U0 K+ A3 ^4 P4 Q M' t) o }
1 A6 S2 ?) b5 v! `+ x8 p2 H return -1;0 a5 B9 t( L+ u9 G
5 D2 v7 `$ a1 ~; d, F" d }
" z/ ^* a; V6 J/ A5 X8 K};# v3 c5 h9 S) O4 B) Q( {
$ L4 r7 C: a6 f. K8 O注意:, e' F( k2 F0 q) g
9 n1 G/ I& V7 B* B! g- I9 u
(1)设立区间为[left, right],终止条件为left>rigth1 w: B' v1 C4 j2 z& ^% | z( l
(2) (left + right)/2==int middle = left + ((right - left) / 2)) F7 z8 J, I: q) Q3 l. f1 j% L
(3) 通过改变区间的左右值;复杂度logn ^- n: T" U' N
6 u* U' D/ ]6 g5 c2 O
2.leetcode 27移除元素+ x$ j1 V( O. Z4 E4 l9 {8 S5 ^. D
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
4 E9 g% G6 a4 ?- o2 n; |, y: F6 a/ g# u" r: o$ j
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。( `3 d' E4 m/ l: s
+ |. a* ^, a' \' d; g: x元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。; k5 J: P$ c$ p' u2 j7 x+ x( z
' ^1 D2 ]3 e4 B
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。: Z* ^2 [" R0 i/ \9 N" z1 Z
# H: P, t+ ?. w3 Y
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。; [" @" i, _( \7 w, F' q
: D8 r* u: N7 M思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
7 l9 P$ G; y5 h, m# G
" ~' m3 X Y0 G; q% ]方法:双指针+ t; v o# W5 ~
4 |% A- s& Q6 V) ]* }7 y- v# b# K7 Hclass Solution {
9 G4 G: }% v7 m. b" I& Qpublic:, m. i5 N; r P" a# u+ y% N5 N" _4 E
int removeElement(vector<int>& nums, int val) {
2 T9 a+ Q' o- L4 L& w! ~5 T int solwIndex=0;
) y/ _$ t N2 O: T! M$ V1 K l/ q for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)& o1 B) q: C; Y4 x
{
+ j' M% t) t, Q$ w9 d# Q! g if(nums[fastIndex]!=val)
[2 C+ }; G+ r) j0 R! B$ ?2 p& ^ {8 d: r2 ^0 l' I7 C" }0 t& S) s: h5 T
nums[solwIndex++]=nums[fastIndex];
0 ?( l. y% x2 | }8 a a" S1 W0 \. R# h4 @6 f3 r
}
1 {( M+ D$ p9 W* l return solwIndex;! V, ~0 \) k# V! t3 Z6 c; X5 s
}
' \% j2 F; O$ V. z! g$ {& ]};
7 O0 L; l& o! S0 ~8 m; ]- F. Dsolwindex:用来覆盖
4 K, a5 B( U0 F8 B2 q
: s# q* ]7 r0 N5 qfastindex:来找删除元素++
- y. ] p6 L5 ^! a% h& Y( Q, i. i) x! ]% B% v: ^1 J) G9 ~- C0 O
3.有序数组的平方: [) c0 h& _- E" |* U& Q
给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。: b6 c \5 x- D K4 Q
# H; i% X; o$ k. S5 S
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
+ F$ f+ k/ G# Q$ f! A. x
- j! C1 n2 |# }& q% F* ]! X* Z那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。5 G& T$ c2 v2 b
; I$ L* S5 q; C* y% F" C+ `. e此时可以考虑双指针法了,: H- f# u$ e- Y" J7 _
, z g( t; F+ Wi指向起始位置(负数),j指向终止位置(正数)。$ z* [5 R3 ^: K# d: f9 e# k
1 S/ T+ F Y* {- c- u定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
1 H# Y( s. d" S$ D$ A. D# e( j6 y& z
5 U0 B* }' [3 q3 ^如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。- e$ M# ]- u4 }! a) M$ q' f
4 [# i4 W) x& S: b6 W9 P2 }5 d9 x
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
( G* z' a2 {0 W. |
, a9 C. I+ m8 I: K/ [$ `class Solution {
Z# S7 l1 H) w* npublic:
. r' k+ l0 ]" E vector<int> sortedSquares(vector<int>& A) {* D# `, U% l0 s& } Q* o5 H" v4 Y. _
int k=A.size()-1;2 R9 ?3 O+ p7 N
vector<int> result(A.size(),0);
( f0 L% K0 O2 m$ z$ v for(int i=0,j=A.size()-1;i<=j;)9 H5 q7 ]" G/ J# ?# j' g
{
; H9 s3 A+ l) \* H1 m1 J6 c //遍历一遍
$ `* f) N5 b5 k if(A*A<A[j]*A[j])- r; w, G* j0 f& z
{
9 _6 x: [) J' |1 S+ j result[k--]=A[j]*A[j];
" f3 V: ~, B7 B: Z$ _+ v j--;
: y4 j$ V) t4 U' a }
( c; l2 r, X. L7 A0 G! l1 V! g else
' G7 e: q0 d' I7 w( t {
1 R" q5 U( U* ^/ B result[k--]=A*A;7 Y, E- \- Q3 |0 C! z5 J: N$ U' C
i++;2 _. G' r- Y2 N
}
" b- [! t; p# f/ y$ j! ]$ w }
8 {& t' F: r' @0 a0 K7 e/ g4 Z return result;8 G \& L0 \, [( i, O/ }
; o' p- s2 E: O2 y& w: n }
3 M8 p! q5 z$ ]9 U( f1 q7 p5 a2 \};) B& @$ m) H- L; x0 g: @3 M& |+ G3 i
% O* J: W$ q# V, A! ^- a4.长度最小的子数组
0 k% H+ q& ]: N9 `& x给定一个含有 n 个正整数的数组和一个正整数 target 。
) n( n% ~6 G5 Q1 f) K/ t6 x4 g' l8 Y! R' h- j0 z
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。* G3 {" S: Y1 ~8 n
, y- X9 l7 ^1 c# E8 [% K. r. s$ |) V
方法:滑动窗口法
* J6 k6 `+ y' w: ^" D# F, T+ S# i \1 C( k6 Y
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
" Z. b3 ~; m( M) q% g7 \4 P, H
0 b- O/ P. ?$ W三点重要:
6 y" d# a% h3 p6 c% ]* ]1 Z$ P: D- D* o2 H5 k' U
窗口内是什么?/ Q( {& d, L! S9 l( J" H& |
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
* S' N. P8 }; u" U. \如何移动窗口的起始位置?
+ x l/ H- A c. y窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
" r/ i+ L% P C9 P/ g; }如何移动窗口的结束位置?2 r( S8 _/ C6 e* N
窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
/ {7 g' R [. } Z
' ?' D$ R( p2 h- W: s 代码如下
( b; t, J" A, s: H, Y4 M* a; L1 I& }9 C1 c1 d
class Solution {6 M! N3 t( v+ J$ y4 ?
public:
7 F7 c# ]' w; K int minSubArrayLen(int s, vector<int>& nums) {
. X/ G! R. m; R int result = INT32_MAX;" A2 a2 p7 ^( u
int sum = 0; // 滑动窗口数值之和
5 f | l5 W* w" g: _$ e- ^" Y int i = 0; // 滑动窗口起始位置9 ?' L- X0 U5 F' P3 Q8 W
int subLength = 0; // 滑动窗口的长度6 G6 s" |$ \- M, {
for (int j = 0; j < nums.size(); j++) {
$ h% ~3 v8 r! y5 J sum += nums[j];( A$ v9 q) N3 v9 N( X
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件" v/ u6 _$ V: v$ Q% M! _
while (sum >= s) {
$ a+ j) \# X6 N0 j0 A subLength = (j - i + 1); // 取子序列的长度
/ q& y: ]1 P+ ?6 H/ ^4 U8 r result = result < subLength ? result : subLength;//一定会赋值
8 s+ h) V8 g" ?: Q% z: y) w sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
# f0 x- }/ Y; e4 y1 w( _# O }* b! M' P* u: ^# P2 U' Y" ~
}5 J8 ? W) R1 ^
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
H* z5 j' r( R& ?- G& \5 \# v return result == INT32_MAX ? 0 : result;. _9 n" e" F7 m1 d+ y$ V7 K
}5 E9 ^" t4 _, ?" Q
};3 z* _) u* t! @
2 @3 |( a6 z1 P/ D" r# o1 u
一旦大于,就减去左区间的值. ^7 A* L; \9 d3 L
# I( i, r. k+ E3 [# ^5.最难题螺旋矩阵||
* U% Q3 l7 g- W4 a8 Y模拟顺时针画矩阵的过程:; k2 e2 j# }8 v- o1 U
4 F! ?* k) b4 P8 u# G8 F) X1 b
填充上行从左到右
% b4 A, J) {# ^! W( [/ i填充右列从上到下
' r3 K9 ^7 f5 z! A5 a) B, P& m% { H填充下行从右到左
5 V. P2 \1 g# W填充左列从下到上
4 D4 c) n/ y ]3 _, u& _由外向内一圈一圈这么画下去。& z& v. O. c* \$ \+ ?
3 z$ Y, {5 l- v2 q* O; T
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。; a/ M H+ L! P4 \
% ` }, e) Y& G2 s, B8 Z" P
/ a$ R" W' N* ?% b _ z
6 C# P! C0 G! O. x. m) y0 ?$ X7 X, L! h! k5 C3 \3 r; M
$ p: I0 H- n' h& l% z
class Solution {
" d/ ]8 d, } V5 A& Ypublic:" f& R% S. P- C5 a
vector<vector<int>> generateMatrix(int n) {
1 ^8 l0 }# Q4 K; |) t' P9 ] vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
0 @3 `1 J4 K( t+ L! u2 [% ^+ y, G int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
- s" g& m! i) E0 G, Q/ m: ? int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
A% J7 @( p- c; R/ w' {$ S7 t int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
! C' o6 @/ t1 f7 m int count = 1; // 用来给矩阵中每一个空格赋值
0 X; x2 ~9 T5 M) Q+ w int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位( j1 N" @8 H+ W+ S5 k& x E! z+ u
int i,j;
' W# i% s) n1 T; u9 s while (loop --) {4 O7 J5 E- {/ p5 @7 D u
i = startx;
) w- b9 T8 U3 c1 d j = starty;
& _9 z: o9 F% Z) M* m9 F# }& S0 e: Z
9 f& A' r. `4 I. J8 u6 f" E7 b5 l // 下面开始的四个for就是模拟转了一圈
$ h3 i4 Z: U0 v6 k5 v. t // 模拟填充上行从左到右(左闭右开)
7 ?; J% H) u$ @3 s" ~* W$ E for (j = starty; j < n - offset; j++) {
6 J! J! U: j8 G8 r1 P8 s1 } res[startx][j] = count++;% }# C; E& ^8 F% L! D
}
8 z$ T* W2 g$ ~' c- `2 L0 L& r // 模拟填充右列从上到下(左闭右开)
' v4 L7 G; k7 y* a for (i = startx; i < n - offset; i++) {
4 d4 a0 c2 I! s' t6 | res[j] = count++;
& u R1 }2 J e }
: |/ s* q3 F& P. n! @, Y9 S7 z // 模拟填充下行从右到左(左闭右开)
+ ~* w* f* S3 P5 @: _. p; h2 ] for (; j > starty; j--) {0 _8 N3 x3 K' F" ?* J( v0 t
res[j] = count++;
8 @3 Q; E0 ~6 e! Z3 q H }
- A @- L B* T! m$ }2 V // 模拟填充左列从下到上(左闭右开), [9 y9 P( s7 k2 w- x8 ~
for (; i > startx; i--) {" R- a2 U7 h4 n# ]' \- A
res[j] = count++;
2 q6 M2 A w1 m2 U }
A& H( j% T( l$ E2 D# J8 e) B! m+ a# z+ }
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)# W2 d4 I7 |6 r6 x
startx++;, C# n+ g, }6 J
starty++;, ^) Y( p- k# p g3 I
0 \. D+ n# ^$ C; } // offset 控制每一圈里每一条边遍历的长度
7 k$ w) }. ~4 ^. c) ]1 u offset += 1;& o7 Q" u5 D/ s4 P; z1 G, r4 {& q4 M
}5 r- h3 H1 F+ P
3 s K6 @" Z1 m( ] // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值3 |9 L8 i8 w- P0 b2 z" u% B
if (n % 2) {
+ B* v. T1 e. C) r. o% Z res[mid][mid] = count;
/ J- l0 J0 M% y; s9 c. T) h# \ }
0 J' j2 l1 A% G; W' Y return res;
( H4 u6 [) u" t( C }' f; y" f: Z1 h. |" a
};
- N3 A; L! v% l( P; R2 z% S# P0 `; W) Z
————————————————
" |: @! u3 }" c版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
; ~# A& V2 y9 I/ t* _" X( F原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450399 b* c4 i' ^8 l9 r4 @0 G
* M, q) X4 S! k/ \& M
- N" v6 B' C7 f; Q5 t$ \1 b
|
zan
|