- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 564448 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174557
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习
5 O! {% c" X9 p" [1 W8 f$ @1.leetcode704
* n, |; w. U# o# U给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。; V5 I8 t7 @( Y) h+ Z ~" I) b- h2 h
" D$ M5 N8 m5 T$ K1 x+ z题解:升序 数组7 g: @3 X$ I0 L, z% p1 H
& `" O% r- d. ]0 B) x1 c方法: 二分法
" E5 O3 i& T+ C( [; ]5 w5 d
. u t+ Y3 o7 K3 ?思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
# i* w2 w) Z* u* u# d
7 Y( H* u @5 c比较nums[mid]和target的值:
, ]9 E9 k7 c) U) k/ s- p4 W `* o& r1 C% Z4 q8 l6 P, L x
如果nums=target,则下标i即为要寻找的下标;
& i R# J. `; H5 s7 E4 j
( i5 a5 ? W/ l0 d; r如果nums[列]> target,则target 只可能在下标i的左侧;6 o+ O0 R" U9 |% V
N" w W$ k; R/ P: i- J
class Solution {
6 J" v* S& {% `- V. L- B1 x zpublic:- ^2 R5 L& g# D; d4 ~
int search(vector<int>& nums, int target) {: G. V' @9 x% c/ N
//区间[left rigth]
- _: s& _. q/ \ A/ r1 a) A int left=0;. i: E7 B! }! l/ |1 A
int right=nums.size()-1;
. ]5 u, ]0 Z0 I6 G9 }: s) s //结束条件 left>rigth) a/ ` L& G# ^* i" X( R
while(left<=right)
) N, m8 J- ]+ } F0 {) @3 ` {$ h" t" t( ?( p2 N
int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]6 t8 R& e5 ]& X& t% S
//[middle+1 right]) P8 o% F( V0 B4 p1 B( W7 b4 D- Q
if(nums[middle]<target)) g! a2 @7 j3 W/ V
{
1 \9 g. G9 l& W; s, T left=middle+1; H( r" C& A' I; r% D
}
, ~7 K+ k1 A( E/ P O' _ //[left middle-1]
& K& Y0 J. z S+ w else if(nums[middle]>target)6 E v: `( S; E
{
- c8 z& P9 U' F; z5 G2 I right=middle-1;
. K1 |& ~$ r5 |$ \( `- o; w" Q }
; ]. k1 f, h( O9 { else{
\- ^$ P( \% {6 R8 B5 c& U return middle;
0 [& X/ k+ M+ X/ \) N } h. Q+ h- t7 [+ l9 ?
' B+ C% N6 D9 z- E C }
( D d6 s+ V6 C$ S& P0 Z i return -1;* R2 L- b# m% p
! m7 A7 d: Y H6 W- x3 H
}; S$ [/ k$ P5 Z' p6 S% p/ m+ c3 h
};
1 {/ Z$ Q( T! v- u6 R# n1 @3 O
1 l4 | V2 l0 W, |2 ]5 B注意:
# m* _; P5 \+ z& c
# J; m& b; J9 z/ Y* }) D( G0 u8 f(1)设立区间为[left, right],终止条件为left>rigth a4 b6 c, R/ U' Z7 p' L# w) B
(2) (left + right)/2==int middle = left + ((right - left) / 2)2 W* e2 [! O: z+ m
(3) 通过改变区间的左右值;复杂度logn( I$ n7 B4 N- u4 c% D: s
2 S1 d( p/ I4 J& Y5 z! a. Q2.leetcode 27移除元素% i& w% K. a2 J0 V
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
$ J" i+ B9 }1 X9 q
4 T# v3 a0 a( B/ X, y% {不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。- w: M' l! t/ ?/ T' P
/ @, t7 e/ T2 n$ e& C9 \, x2 U' ~4 x
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
* `+ C1 w" U% v: z2 W3 z! l5 w* m3 ~" m3 r8 Q; H
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
) y- f+ I- @! D/ I5 e, d P% f( U0 T1 I3 [
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。% R" ^- e: N ]+ {8 Q: K; z1 b. f
$ h8 q8 @9 H8 \思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
# A7 H0 i2 c* W0 C) H; Y
. y8 q( H! t; v$ s# K, \方法:双指针0 u1 P& H) H# J+ Q# k
0 l$ `: I" `% d! ]3 |class Solution {
6 W4 K4 J5 K/ P. F, c7 Apublic:
' b' V. C; l2 b$ y! J- Q7 v0 G int removeElement(vector<int>& nums, int val) {
$ ~) e7 e& a( Q( H) O1 h int solwIndex=0;, T7 i4 M: Q/ R7 t0 {' h( b% V, }
for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)4 X0 E+ A# n# u; N" f$ X' L
{1 o8 p' s3 \ D2 p+ }
if(nums[fastIndex]!=val)
( U7 v! a4 K6 o/ E+ U5 y {1 Y) S7 h5 \5 Y) X0 _. k* u7 s
nums[solwIndex++]=nums[fastIndex];
. E# N9 O6 `8 `, M8 b+ _3 x }! x# W4 T9 I/ Q A. \% Z3 ~7 T
}" ?; D. \( W9 M Y% u) @
return solwIndex;
, X- m/ l* R& ? W/ o. X }
9 |5 X/ Z+ j" v};
! [4 ]3 |0 C8 A" `' o6 A/ Hsolwindex:用来覆盖2 l+ q4 v) x/ ~0 U4 U
6 A( z/ T6 q* @7 Q. sfastindex:来找删除元素++
* H) f0 c( F; q( V$ P9 @! b+ V) q2 _7 A
3.有序数组的平方
- T$ o1 r- ?8 z9 o8 [& r给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
" X6 I6 T! I+ D' |7 D$ |
- j4 F p4 |& ^2 D1 u% u数组其实是有序的, 只不过负数平方之后可能成为最大数了。
( |1 F# C. Q% s5 k/ [3 v
* m0 s: \5 g, x# l. k1 _3 J那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
( P* J. K' }1 ^+ y; V$ g9 }9 }" g
1 ~' ]% ?- ?' O* S/ V5 {" l7 o) z此时可以考虑双指针法了,
* M) U' X. |" q. n: X
6 t) P# o3 R! N+ pi指向起始位置(负数),j指向终止位置(正数)。0 D- |0 u: ?8 w
! W7 F( n8 N9 {1 } _. ?定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。* [9 O9 A) [2 i6 M
# [* s9 t) Z# D9 o+ F% j( b$ S
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
! e# d3 g0 X0 c3 G3 x* h& S6 l/ H6 n' z. L0 ?- o4 w1 S u
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;. I$ Q" x) f) ?, F
+ N# b9 h& c; _" r; S+ `0 Kclass Solution {
1 J- j, k0 `, U8 y3 ~8 P; h; ipublic:
9 G, V3 W9 t) U: ]7 F vector<int> sortedSquares(vector<int>& A) {
) ]# a3 y$ N# n9 z0 t7 f3 ~* { int k=A.size()-1;
; W& D$ r- V7 G6 ? vector<int> result(A.size(),0);
1 i- V& N' j: c" W: @ for(int i=0,j=A.size()-1;i<=j;)
& @5 m" U$ y$ H {
. Z! z% }5 M1 v) n. Y" A+ X8 @ //遍历一遍2 o5 w1 A- ?6 p( y2 M l
if(A*A<A[j]*A[j]) m$ Y5 q8 i- \6 U! h
{
; Q( X; _! Y9 I result[k--]=A[j]*A[j];0 W P7 _9 O- e$ O
j--;
' Z& N6 p5 T: a8 e0 Z- A: y }" n1 [! b1 ` n1 B
else9 f9 G% p4 I( D7 @, S. a% u
{# P/ V- I- X4 Z2 }# T! s+ `9 C5 e
result[k--]=A*A;9 V0 u/ e, r4 P- E' P
i++;7 g8 w; r V2 H
}4 W! B% L }; e+ O, u
}
8 y3 g; W2 {( h" z; s0 q return result;
5 [1 ]5 e( R7 ~" q) ^
2 s# P, ]( D3 \% H4 w. i1 r }
0 { r2 S5 a- x1 s};
- q9 L6 v) F$ \5 T3 Z# ]/ k
/ ]" v4 J6 O5 z$ ~6 } M ^4.长度最小的子数组* ^: e4 v5 q+ X8 M/ `8 m
给定一个含有 n 个正整数的数组和一个正整数 target 。+ B7 g2 i, }0 @$ |, b' R& S
; u! o) u4 k; x; C
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。# i: m5 b) M m% ~9 W$ w9 z
3 K" y: D5 m% s0 f& L' ?方法:滑动窗口法( u2 U1 a/ C+ n p2 S0 P& [
. J" X G2 p5 N- W" Z就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
& Z* J N! q0 p, x
; e5 D/ T. A" X7 f6 j: ~& L& Q三点重要:
% \/ Q! r8 _0 [& f( M9 p* M d3 j
) C" N( C, s) G9 m3 F窗口内是什么?
2 L i- I" d: B+ r8 ~* z窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。! ~0 f4 x4 ?0 K* v$ Z) u0 N6 k
如何移动窗口的起始位置?" l `( T3 E; h1 [) c$ X1 v( f
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
; ~- `- d [- q如何移动窗口的结束位置?
}, i9 w; E; L' R窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。, _' g: {/ Q* B% L" V% ?7 ]" S$ ^1 [
' @5 Y' r) w" F1 m
代码如下& A1 H7 O. O* t
: X. ~4 I- z, X; q7 v; [* yclass Solution {
" O p7 i/ y4 K U' F$ N9 A% Xpublic:8 R% s, {. j1 r4 m/ P
int minSubArrayLen(int s, vector<int>& nums) {
2 o3 Q2 Q+ c! C7 I( u int result = INT32_MAX;! y) F9 l# {7 z1 n
int sum = 0; // 滑动窗口数值之和
5 t- k& {. X: \' V6 a% z8 g; o int i = 0; // 滑动窗口起始位置
/ W' v; z/ J& o int subLength = 0; // 滑动窗口的长度4 w4 a. f6 T2 m# q
for (int j = 0; j < nums.size(); j++) { Y" k% ?8 j3 d. P, g8 ?
sum += nums[j];
( B' Q8 v# e6 ]# a" }+ B$ ? // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
8 R. D/ s8 W q while (sum >= s) {" f/ `$ m5 F( v/ }: g# Z
subLength = (j - i + 1); // 取子序列的长度
7 y8 S" X3 g, p, U result = result < subLength ? result : subLength;//一定会赋值- a9 U ]3 ^5 `* X
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
" j6 s- C9 g; q4 N2 _5 K/ T+ S }
7 b& j5 k3 T5 F3 n }
! Z. s/ x' w# L! ?- B% t // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列! f% C: _- y1 A2 O
return result == INT32_MAX ? 0 : result;0 m4 Q) w0 g8 E( K4 W
}
/ `$ W# [0 ^- V" ~: V$ E};; R. R# B8 ?0 l$ @' W! F5 C, ]
' c# @5 @3 ?- M% R1 ^' K一旦大于,就减去左区间的值) V1 S! V( E I4 G- p$ w# n
, o% q- A. _# m$ b+ b5.最难题螺旋矩阵||
: f4 P c- C9 y% ?! a1 ^! L模拟顺时针画矩阵的过程:
3 n# M3 ]- X w- M1 C$ E, i
8 \' K2 i/ v6 C; H填充上行从左到右7 O3 D F( H. [0 i
填充右列从上到下
5 {9 ]' E; r9 T+ R填充下行从右到左
& T9 D1 d1 J7 ?; _0 m& [( D i填充左列从下到上
6 O; T6 x, x5 `- V" Z1 V, q由外向内一圈一圈这么画下去。
4 l: f0 W& I. I$ W" u/ L1 p) B$ T8 [/ D/ P* H2 N) s9 R% M1 {4 U
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。1 x) n0 ]+ Q9 x$ ?) a, E* ?4 P$ L
?$ n. L3 F0 }4 y, y
* y2 K- I: a+ D1 e* N
7 Y& x) E9 X6 R* A; Q% O( z
% E6 v- d8 b C- K$ o0 {- z. _5 c3 P, d& A) Z/ B
class Solution {
' U" P! g6 B2 V7 o0 u4 ~* O' Ipublic:
* [1 C9 {( V) e$ Q7 U% _ vector<vector<int>> generateMatrix(int n) {3 r- X, i( j1 h: L" U
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组% L2 p/ @" |) n0 g& b
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
; U% {. x5 |' R. Z int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
6 D" M& |/ w' F1 P int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)3 \$ S" e6 M: c
int count = 1; // 用来给矩阵中每一个空格赋值' L4 B" j5 y& m/ d) F- V, f
int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
8 z2 b/ P+ p$ n* [7 D B# m+ L int i,j;
- U8 j) V. G# C3 x/ ?8 { while (loop --) {
: s3 E) V! j; a4 V) l. U i = startx; t6 Z0 F, q) @
j = starty;
5 a6 W8 c! G q w* M& t) |; h" ]/ {
F* H$ P+ A# | // 下面开始的四个for就是模拟转了一圈
6 M2 Y: A7 X/ o, M6 g4 @% E // 模拟填充上行从左到右(左闭右开)( r# Y+ d* ~7 a; d6 I; q4 A+ [# M
for (j = starty; j < n - offset; j++) {
' S4 Z; A6 ]1 ] res[startx][j] = count++;4 A# T1 L- k: \2 {- V+ B
}
1 N6 U& A) ?- q! W // 模拟填充右列从上到下(左闭右开)) b% M9 T5 {4 {& }+ X
for (i = startx; i < n - offset; i++) { |$ n7 _. z% M" v% r7 C- S
res[j] = count++;5 n' s( y6 E; _9 i" H9 g# |
}8 ]6 [: S5 y3 k4 t# W& c
// 模拟填充下行从右到左(左闭右开)
6 R9 {/ O) ?0 W) z' p for (; j > starty; j--) {
6 z7 A4 m. _: e7 [ res[j] = count++;
/ U2 f' `; U* v' f: L }, w; Y- \, b/ i9 ?: t5 m1 I
// 模拟填充左列从下到上(左闭右开)
) t& N+ h1 y& G) `( j& h: H' P for (; i > startx; i--) {
. Q3 q* l4 s5 m1 r3 {% h res[j] = count++;
1 O; ^ e' u" o }4 @1 v& J% |& I2 p( a8 x, l9 a
: H8 i; q, h* P. Y // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
$ U9 p0 L1 d4 e2 a startx++;/ g4 y7 k% D/ z5 w9 k# k2 N- Z* [, l1 c; p
starty++;
4 ~! s' F+ Z3 j- W6 K$ F4 l/ d' j3 _
% h* J) Z2 J8 l! k" t8 o // offset 控制每一圈里每一条边遍历的长度 Q% `5 |% Z% n2 o4 p0 a9 s: X
offset += 1;" ]2 S8 L& R* S) T
}
$ T9 m, x/ h* e; N8 e# r0 W* ^& x V5 |& s4 E% T, U" R, _( \' r4 s
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
6 f$ O0 _* p( W# G3 U1 C if (n % 2) {, F. A+ Q1 q# p
res[mid][mid] = count;
- M. v2 V$ ?. x4 V }9 s0 l# @4 L& X! z+ @
return res;: ^) @% O) O8 X; [- j3 Q) T% A- Q3 m
}6 ~! Z* K& n& W$ @ n8 U/ e( F8 S( Y
};
# y. n# c: v, Q5 _2 I6 i+ b& H! K4 U: }8 r+ b+ j
————————————————9 B( c5 p0 p O! }
版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。% u7 h& @. i$ y8 ]
原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039! `1 ^9 q: P# I9 G7 k
2 Z; n! |# C4 f! p5 d0 b0 ~: t6 [/ F, b; z, x5 V
|
zan
|