- 在线时间
- 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 F5 Z; [; G& b* Z8 J
1.leetcode704% m0 h0 V0 v4 X: V& t. b- Z
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。# R4 B$ e0 j5 ?: h7 Q! e. P5 w* w
; u7 c- i; c+ O1 J3 h% T/ w3 U
题解:升序 数组3 y. b2 R& i" u+ W v
4 \# G, y$ ^9 x0 ]方法: 二分法
, {% `5 f8 K5 Q
% Y" d: t8 X3 l; ]+ m思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
/ `: r V. L" Z4 ], h: g) x& W; z4 `& i; S2 j
比较nums[mid]和target的值:
! L. u% c2 r) T$ I8 P
* @) u! Q2 T5 l7 ?- L7 K如果nums=target,则下标i即为要寻找的下标;* \9 u$ T: Y+ X4 F- v7 b$ M5 i
/ d4 M/ z$ w0 E0 H) R, m7 Y) F
如果nums[列]> target,则target 只可能在下标i的左侧;
( z$ ?+ f1 I6 L& j; d) |. ]2 P+ l/ B1 t9 m2 }; t2 k1 S
class Solution {
! c" S, ^) L4 vpublic:- C1 H! [% H1 I# [
int search(vector<int>& nums, int target) {
2 f1 m8 Y, {3 G! B9 [ //区间[left rigth]$ ]- J3 G( z- D/ e* }8 K
int left=0;
: j, A) j6 F# A. F int right=nums.size()-1;
$ e* s# H( p" w* C //结束条件 left>rigth
4 C6 @" K W! Z& n while(left<=right)
( X3 L% b3 _) _ {
- Y4 ~# T/ h4 s int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]
# o5 T7 ?# O' L3 |) E; d7 T //[middle+1 right]4 s" a: g; ]5 N0 I F
if(nums[middle]<target)
0 @ O7 Z0 X. B) ?8 t: M* ]8 G/ | {
! V! k# u+ s( { left=middle+1;# M- c* D* ^/ q5 ?0 O( H9 a
}3 \# s* n2 m/ r( z4 B
//[left middle-1]
& M& _2 z9 ~' J1 V7 r7 R else if(nums[middle]>target)9 O0 |+ m/ V& ^- s" x' j
{" g `: y* R }/ Y( K( F
right=middle-1;
: s' O# \* y$ Y4 [8 O }3 g+ u* ?* r& X8 C. c' r, ^$ K( f
else{
9 O. P) A" K: q+ Y& U: v return middle;
3 s& `" @/ l5 v& Y+ G" E' O }
, u2 Z) @8 d& a3 Q* M& n# s8 r; q2 J0 r1 @, k
}) A) f g+ ~$ f! M; H6 k: t
return -1;( C- i6 n6 n; L4 F. W% X/ g2 ?+ k
! |7 x3 R8 `7 C6 L; Y6 Y
}
4 e+ N& B0 G" Q1 @6 u, ^. Z2 X};
) Z, O' g- S0 p& I5 r3 L! M8 C0 |$ M) I# M
& N" L/ U, P# z& L o& K注意:
3 T! v" X1 J; M; g3 }6 r& ~% p; D
(1)设立区间为[left, right],终止条件为left>rigth K% A4 f8 F* I: L( s$ o8 i4 u A
(2) (left + right)/2==int middle = left + ((right - left) / 2)
* X. {8 W$ R1 u3 @& u (3) 通过改变区间的左右值;复杂度logn v+ c& i6 `" d4 E* s0 l) M
7 F+ M1 r* W1 u( d; i2.leetcode 27移除元素
3 {, k/ I0 V) Y给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。5 {& S0 g: _9 L! ?
8 ~3 |1 `" x4 P3 G6 \不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
$ ?( H0 b+ ^! F: r% k: _: B: h
6 Y9 s% O3 J& b5 ^ Z元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
: X3 [' e/ n2 l( |
* h- H& _3 Y. K! G# Q1 ~) t' [0 o示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
- k0 d- c9 ]! Q8 K: @) j$ _3 d2 `4 _( e9 x: ^: [
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。! c, q5 M" Z! X, U
% Q. e; y" w' b& g5 ?6 W' A% R
思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。, g5 a2 u8 x" C/ j) A! k2 T
~7 ^5 A1 Z: T2 t4 F1 s9 d方法:双指针
0 t6 k+ I; M) ~+ u; t. k- X
* ^4 x1 D# x+ Y* i9 i% Uclass Solution {0 d, C' E$ y8 _1 I5 I
public:
- o+ k+ A7 U3 Z. j) m! H: P int removeElement(vector<int>& nums, int val) {
1 X& J' F9 T$ T2 I. T5 n5 l int solwIndex=0;4 [& ?, Z' k9 H: ^4 ?( j! M0 b
for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)+ n$ s) e* m9 E2 w
{0 U9 X$ I6 o% [6 d# J
if(nums[fastIndex]!=val)' B* T1 q9 O' y: I/ D
{+ L0 e% l% o# B2 x* ?
nums[solwIndex++]=nums[fastIndex];
- j, I9 z) ?* m7 _8 y }1 W) s+ c9 j6 ]& g; ?& ~
}
+ m7 `; b. l, l; a return solwIndex;
8 E" D7 t$ o% k: W* J% ~3 ?8 w }
- R7 I2 W, S. J5 l" {! |};
( {2 }8 [2 e1 F2 y9 gsolwindex:用来覆盖
! I. q: i0 g, i9 {. {9 T* T; z. z) c- T" k: Z
fastindex:来找删除元素++: z, r4 U2 \1 E% G3 K* b$ X) W
. q* f; h# o. Z3.有序数组的平方4 ^5 V0 ^3 [2 o7 @" B) b+ z
给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
# {/ H0 g' O' r' X9 h2 q+ W3 y g3 H, r! }5 V$ \8 `
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
/ x5 O" \& |8 N: a* w: w4 c5 J' |* R, j; Y) c! \* e U
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。! w, g, s4 ]5 Y& B; W
! }: p9 B: K5 Z9 b
此时可以考虑双指针法了,- A4 G0 `0 q1 A F, e
; T/ A/ ?/ r8 A/ h/ u3 L( gi指向起始位置(负数),j指向终止位置(正数)。
6 ^0 E: I, Q5 B$ d9 o. [+ T' _- n) R0 L/ f
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。; }' S5 |; ^/ V! J
. ~5 \7 h( \8 d如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。7 l: p$ ^) A3 k# `/ Z/ E
3 p) Q( i) r/ x1 u3 x0 m
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;' n0 s" G, a4 V# l
2 A$ j; X* U& B& y$ M2 y2 I
class Solution {, A2 o0 Z8 l$ K6 u
public:! C5 K4 O' {6 e0 p2 W6 I
vector<int> sortedSquares(vector<int>& A) {7 G+ O5 t! ^4 z/ f/ |" T
int k=A.size()-1;. A" U- u% Y) O3 U, D
vector<int> result(A.size(),0);5 D9 S3 y9 d/ a7 g2 g5 {. N+ e/ `8 A% m. N
for(int i=0,j=A.size()-1;i<=j;)
& g/ G; H! C9 s {
1 U# U. ]. ] R //遍历一遍
$ o0 f0 k, Z, ]1 J; a7 w; l- l; G' M if(A*A<A[j]*A[j])+ V+ a; K& |" e/ y/ u# q
{0 I- W+ G& g: V/ U' _' Z+ Y
result[k--]=A[j]*A[j]; ]: h! G0 M6 s( s6 n9 _# r) O
j--;- d: {2 t" ^7 F$ f+ e( [5 E
}
% F) D% I, ?& i" M' v$ f else
% b) i) K/ f8 g6 e2 \ {
% G) d' t) V- G% L7 q6 K result[k--]=A*A;
/ r) B8 D/ \5 X# \, r+ n6 B i++;* I+ P2 ?1 g6 I, f) Q* r1 \8 z
}
; r! U( Z5 H) s }$ _* p" \- U$ r2 `' w* e% U' t
return result;
2 e; H- V1 m: e) q" q1 U/ m
$ v% f; l7 v# R2 ]$ @4 B }
" W {' c0 r9 ]. y" Q};
- j/ `5 q* t" S. z; g
, S V8 j8 [; h3 m7 n4.长度最小的子数组4 g: X! p$ R$ S8 E: c: v
给定一个含有 n 个正整数的数组和一个正整数 target 。6 T' m$ V# N( T. l! X3 r
9 |0 |: y4 G$ }/ w' o$ ?找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。+ I5 W0 r$ ?: T& X$ x
p4 Q. i9 n1 z4 ~# H; J方法:滑动窗口法
: J' Z' P# k9 l' c$ g# l0 Y; }, G5 _& u; t
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
8 V( I+ j1 f8 o8 N3 I, b% T$ `" \$ b
三点重要:/ w0 t) ~ V+ W: g
! e8 y$ Y+ x& b窗口内是什么?
% _% _8 D# \5 b7 ]( G Z- N' h窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。! Q" ^. c% c/ P
如何移动窗口的起始位置?
( M6 D# q& i3 M$ q' P窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
' Y. a5 C! g. M! n' p如何移动窗口的结束位置?
3 d1 x6 p/ d+ T7 `8 p9 e& ~窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
0 M) M# p# K0 H& \2 ]
: @" y3 }1 C3 s% @ 代码如下/ @6 u' ?3 m4 T( d/ W( w
# h( u* I$ Z6 }9 ]class Solution {
4 e9 F( ~9 ]. Jpublic:. J! N$ j$ D6 s5 z
int minSubArrayLen(int s, vector<int>& nums) {( C0 z' D9 ~: s" c0 g+ f
int result = INT32_MAX;
) C( t& N9 T2 B# _ int sum = 0; // 滑动窗口数值之和0 {* j* ~) `! e( Z6 i7 i* i, q3 l
int i = 0; // 滑动窗口起始位置, G( ^3 G* [+ @+ n
int subLength = 0; // 滑动窗口的长度1 z5 v8 g5 u# }' V
for (int j = 0; j < nums.size(); j++) {
6 s. C( t# W" U sum += nums[j];+ }6 F# x/ B4 U# n9 \/ s
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件; |9 b+ I. I% f0 q* k
while (sum >= s) {" B" ]- `( Q$ l
subLength = (j - i + 1); // 取子序列的长度9 s9 v& k4 ~6 x3 }
result = result < subLength ? result : subLength;//一定会赋值
; z @2 I& E% X8 s sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)0 F D' x7 K( I6 v
}
9 @1 s: f# o4 w+ o. S }1 e0 W: R2 l' T7 s2 h
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
$ s0 p0 i; ]* ^; C( ~2 F return result == INT32_MAX ? 0 : result;
- a) Q4 Z, R, }! l1 m n: H }, f& d7 ~ ?: }8 k7 X l
};7 O$ W3 ]( b8 R I, n
' l# R) _2 W& G! W8 C一旦大于,就减去左区间的值& G0 \$ r. Q; q( K, d3 A+ v; V
" t' a) R( T( e6 ~5 p
5.最难题螺旋矩阵||' a, d3 B3 X: O2 Q" F0 B
模拟顺时针画矩阵的过程:$ V2 L% k! o3 z7 S
0 Q8 x9 _) J( n$ [
填充上行从左到右3 b6 p& ?; R$ k$ T7 r4 T
填充右列从上到下
0 R% o8 u. J0 i5 P. s填充下行从右到左" F. [1 O+ S- m4 G
填充左列从下到上
: c$ j: T0 r1 O& r1 J( C$ M- [由外向内一圈一圈这么画下去。& k5 b; i2 a7 F/ `
, D" J' }! I# I& J5 C
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
9 n3 r; S. E3 I* s" m) B5 W
& { N9 P; H" v, [. y' o
7 E4 z' _1 f. M8 ~9 D
" f7 l+ i0 ^; |
$ E/ N/ o6 o3 G- w X0 w
' z; R$ i+ \2 jclass Solution {
& d8 P3 \% o, P% D7 |: Z5 jpublic:
* _) K! B0 q. O4 Q6 x vector<vector<int>> generateMatrix(int n) {
" T1 y4 ?. f/ L9 s3 Y0 b& `7 H. ~- w vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组9 l% W6 p# e0 ]# R3 t6 H
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
! |- ~( W0 R, `6 H( W int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
8 K( T, p& v, L# V' ^& F5 _8 g4 u2 m; _# u int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2). U5 j2 b3 x+ x, `4 C m& x
int count = 1; // 用来给矩阵中每一个空格赋值
. O9 {2 a0 Y% h$ q; h2 D4 v2 _2 g1 j int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位2 v0 ]! | v7 Q: Q' w% y
int i,j;2 r/ B( }0 L& i+ l6 d
while (loop --) {/ P0 ^7 e: X( Z' o- @0 c# c
i = startx;
+ t ?" ~$ R0 T/ { j = starty;/ g! L) A$ n( I- r0 u8 `
2 d* M0 [( |( v% L, o; b( [
// 下面开始的四个for就是模拟转了一圈
: O/ q+ ]+ W$ |: k // 模拟填充上行从左到右(左闭右开)
1 n0 c- ]* m( r& c for (j = starty; j < n - offset; j++) {
/ f1 I. q8 |" W- s) {( D) e9 X res[startx][j] = count++;
* ~4 i7 r8 n/ D+ \& A, S- X0 i- Q }6 o5 D& P% G& E6 N& K
// 模拟填充右列从上到下(左闭右开)
. K+ |4 n# a1 p* E6 c& \ for (i = startx; i < n - offset; i++) {
0 F9 b! n; S: v1 v* X$ \: y- R res[j] = count++;
" i5 q) z$ b+ z4 {5 s }" H. I' f1 ^4 o
// 模拟填充下行从右到左(左闭右开)9 [, q( K2 j' g- b
for (; j > starty; j--) {
8 @' ?$ w$ y5 h S1 D" P res[j] = count++;
2 K# K2 S; ], c4 V9 w2 g }
6 t4 e8 K9 u0 d. T9 c- R) S. N // 模拟填充左列从下到上(左闭右开): ~. i- Z- e) I6 A+ g9 F% e1 g: t6 G
for (; i > startx; i--) {
0 D$ N$ G2 ?& j5 |+ ] res[j] = count++;
, f# b- i- P9 Q% r }. D+ S0 F0 R* X$ b) S s
A3 F9 p4 c; [) j // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
( h' l& b! b" I$ y/ n7 p O startx++;
# P' v- I3 j$ R0 O3 e7 L starty++;7 c! t# t; b, Q' ^
, g9 V& X6 T: e // offset 控制每一圈里每一条边遍历的长度+ J& N8 L+ i2 o! R
offset += 1;: Y' ^" V; H, s7 P0 b+ e5 E9 y
}
% Q7 b; }7 U1 B+ b; m$ V8 h
/ z4 \/ S# y& g I // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值! j; b1 {2 L0 A5 y4 a
if (n % 2) {
9 Q5 d2 A0 m$ ?( L, W; I res[mid][mid] = count;# Y0 h( Q3 `6 |4 M! T2 o
}2 B) D. k) D+ q' @. G1 k7 ~* ?6 T1 l
return res;
! v7 u* I- b9 m. Z, @ }
u* F# r" m4 j6 m0 x0 t};
: R. K. c8 A& S9 W u4 C7 v) [' z0 e( g9 I4 V$ H) w7 o' M
————————————————
6 {, {1 j- I/ N/ u版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。2 r9 |$ w+ V8 r: B3 W3 l2 N
原文链接:https://blog.csdn.net/qq_62309585/article/details/1267450399 A- O1 F6 [+ H8 l0 ]1 F5 U" M, E
W: L7 n, I$ R) O8 @% U( \
' O; ^$ O& L$ k |
zan
|