- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 565606 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174905
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
数据结构之数组练习. ^( f7 J3 v2 b3 f* Q, d6 R
1.leetcode704
/ A( y0 j% ]2 w' }) C; j7 s6 v给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。$ }. c7 t D a% @: V
( R6 \ G$ e! \% \* Q# s0 S- F题解:升序 数组
' i# X! M- b- \0 |8 s7 `0 W' j6 E. p# i( Y, {- I/ e
方法: 二分法
0 K8 g; V$ |4 O8 j/ r2 x
5 P& K5 A8 T. S0 h6 G1 w思想:定义查找范围[left,right],初始查找范围为mid((left+right)/2)
* \4 W5 V- U& _1 v3 U' z% j3 R7 ~% w g. ^6 q7 x) U8 z& K: U! g
比较nums[mid]和target的值:
# |7 ^, x& Y* ~' U k; w7 V# @2 H* j
. `! {$ f# B( r2 O T如果nums=target,则下标i即为要寻找的下标;
* X# ~0 S& s" f5 J$ I# v
$ D& F5 C4 P3 g9 @2 c/ f" m) u8 m如果nums[列]> target,则target 只可能在下标i的左侧;
, a% P, C1 p j2 x2 t% u2 H
1 V0 A- D! V5 V' U+ }' jclass Solution {: m& B3 b/ p6 x& K5 C
public:
4 x! Z; _3 R7 E! `* ?& t int search(vector<int>& nums, int target) {
3 h1 P, f; j( s+ e0 z1 i0 \+ {8 I //区间[left rigth]; [2 @4 [, c; K2 A' r& C2 @
int left=0;
4 ?; h0 ]6 f6 e1 q1 U int right=nums.size()-1;7 {2 H1 Y) o* G( T7 _$ N
//结束条件 left>rigth
; \) u' h6 h9 z) ~: N6 W0 `7 f while(left<=right)
A- P5 {% ]0 N5 K/ k4 f {+ f& _. b4 y: a/ V: ?" ]
int middle=left+((right-left)/2);//始终保证 有变量 [left,middle]或[middle rigth]* L) R$ j3 M" o) ~7 {% L( J& c E
//[middle+1 right]' O2 {- Z. u2 Q; i
if(nums[middle]<target)
: v5 D6 E& m$ W! \, z: }* S x {
6 h; C9 _/ A2 K# N: X7 t left=middle+1;
7 B2 I* E3 G: L; q }
/ m# t- v* n( j7 w# f5 z //[left middle-1]
$ w4 N% ?% y: H8 u' o* t8 Q9 q else if(nums[middle]>target)
6 s( q/ G# _# Y2 D3 e9 t a {8 o# [0 F. Q* ]2 P: R( Y1 w
right=middle-1;/ h2 ]% S3 Q6 q- ]
}0 \% |. Q# N# u" ?
else{/ {. I! {! w4 C8 m+ N+ f; j& A
return middle;
4 E* L- [, ]' d# ]8 T }4 ~0 t0 O7 q6 [0 d9 }# T
% H& Q4 i* B1 u/ ^8 F ? }
( W/ \0 S/ y5 W2 t/ t" L5 m* e return -1;
4 W$ H' C) l" @; c, }& A1 F7 D8 O% G5 g0 @: z4 U: A
}
: P% g# D4 T8 t: K& i};
* N( }1 w' U: Z
! ^9 m# b& x$ b' A0 s2 W注意:
s1 y3 i9 d+ T$ ~+ M& ]1 c$ y
+ M3 [- Q b: p4 }(1)设立区间为[left, right],终止条件为left>rigth
9 ]# ?5 b; }* i: b6 n: a (2) (left + right)/2==int middle = left + ((right - left) / 2)
' A5 R, x" m. M( Q3 Y, p (3) 通过改变区间的左右值;复杂度logn
% a& O2 u/ H- a8 D) F" a
7 C- X. }9 C) v' Q& A4 j2.leetcode 27移除元素
" v2 o1 ~+ z) w! K5 U: o; [3 N给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
& n/ J6 n% J) x- e, m+ T& M
& |& L2 e/ `; I @不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。0 x7 e6 k' D) i3 A& g5 g" V! f1 P
2 \! I2 }0 y; T$ U4 s7 q$ x2 [( G
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。% O- L! |$ N% }- e7 V' e
; F: r: r) @) X' B& ?4 X示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
$ M) F. I0 v. H" k0 ]+ T4 o7 |3 Z# o, A2 B
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
" k+ m7 H: g; I5 o+ i
0 m/ s% N; B) m- g, s+ f思路:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。- S) e% h5 y+ o2 k" k( V
4 y9 E) Y3 Q" I; ~
方法:双指针 R* [/ S2 U9 X/ ^& I- x
6 u' L1 [4 L$ U% n4 g4 J: Jclass Solution {
3 x4 ?- s5 l) |: \* f) mpublic:, F1 ?) s1 {3 o8 {0 q( W: d- I# l
int removeElement(vector<int>& nums, int val) {
9 m q) l' k, d ~2 \0 @ int solwIndex=0;6 N, f$ q* d7 ?, Y
for(int fastIndex=0;fastIndex!=nums.size();fastIndex++)* @8 X2 H5 I6 `! w
{0 v4 q; ]; @" o5 ~
if(nums[fastIndex]!=val)
4 u8 c9 u3 i. X5 @: {0 @$ P* Q {
! O- _ z- q" J5 y/ M nums[solwIndex++]=nums[fastIndex];
3 O3 I" v# d- }1 H( V }9 W! l7 g4 u6 S2 u# ~3 e
}
' s5 \; w4 s4 e8 w& T return solwIndex;
) j0 _/ r% o- [8 |9 T }
% m6 ]# `8 W5 p7 y8 z/ a};- a) }* F- O0 t3 x8 _
solwindex:用来覆盖 `$ e5 `3 x. r8 q H
* K- M& m7 K* O4 U
fastindex:来找删除元素++
% I% H1 y( n) d* r0 c( K' O# n& E
# P* W+ R+ g/ R# u3 k/ J3.有序数组的平方- \ ^6 ^. ^' u9 N
给你一个按 非递减顺序 排序的整数数组 A,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
& q: S0 \ ~9 G( ?+ N4 W& \, B$ U6 b& [
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
$ a- @8 O8 \/ {! e3 \5 j% N- k7 b l0 h4 M& B
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
( e# l# W4 k2 r# V7 C0 K% f$ P2 T# q2 ^* Z8 a
此时可以考虑双指针法了,
4 D. Q) @; |& i- \% @" W+ D* _
+ ^7 W d5 _ n+ e7 R" {i指向起始位置(负数),j指向终止位置(正数)。8 q4 u! @( A) ], l1 ?
+ s+ E7 ]+ N1 Z% V; b
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
0 _$ `- X7 V6 R5 R! j, j0 @( Q# X, i) x+ n1 N" C" n* A
如果A * A < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。
; @8 `& c _7 q/ S: S6 H3 J7 T- ?& e% x6 Q; c% o3 {: A) [
如果A * A >= A[j] * A[j] 那么result[k--] = A * A;
% R7 F5 K) A# Q: I- R6 o' S
! |$ V# _* B% Oclass Solution {
- q5 H) |5 `) P, e+ Apublic:
4 A- b* m3 F+ Z$ Z/ Z8 p vector<int> sortedSquares(vector<int>& A) {
) N5 w2 h$ }& D$ C+ }# N int k=A.size()-1;
' g: p! y8 t, i vector<int> result(A.size(),0);/ j# m: k) j/ z& l
for(int i=0,j=A.size()-1;i<=j;)
9 U6 z6 k+ R; u8 { {
4 R$ A8 V( v* s; P% C- M4 S //遍历一遍9 q1 H& E9 @1 E$ l. j; g
if(A*A<A[j]*A[j])( j( b% L+ D6 s2 d
{& o" D' p0 t5 l6 s% n; h" X
result[k--]=A[j]*A[j];
; f& |) D+ I9 P* z- P, W( X j--;) E: k, x. Q- Y6 T
}
5 e: E% S0 [! y$ Q1 s else) M4 C: I. ^) X' Q0 E
{# l& F' F! U: B2 V y6 [9 c
result[k--]=A*A;" v+ c6 a+ q; s4 {. [
i++;! C' ` m4 {# O& e6 u1 ]
}+ s- l+ N# M& y* Y, M
}$ a2 V( \4 B# H9 j ]$ A6 L8 y
return result;
: K) [& b# t9 t2 z; B! P, O% i* s% H7 p- t) H+ I
}
6 k/ S* O J5 W% z+ @* m) T3 {};
& @2 |& j2 I+ J( ~ Y8 \+ q: G" Y! t% k1 D+ U- u0 e8 a9 S; k
4.长度最小的子数组
! c1 P% M' f- T5 [4 T2 l给定一个含有 n 个正整数的数组和一个正整数 target 。
, x" g$ A3 G1 j6 V N* y9 g0 U5 G
7 v2 y. D2 r. J# e4 p/ `找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
/ q. ^# c( ^( X9 A) [6 k5 O' b4 G2 K5 x5 l# T. S" B0 d
方法:滑动窗口法6 v9 W; J% F% J6 B
! P5 S/ r1 w6 g. x& o3 O
就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
0 R6 j+ Y8 S5 E- k- V
. {- ~- F! L9 ^6 e三点重要:
4 M) @, ?8 ^# g0 Y: J, ^5 ?& T. l. m7 W0 S0 ]2 ]' @
窗口内是什么?
6 [: O e; T$ X+ L窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。7 P$ f4 l4 i5 P, U- g, p! g1 m
如何移动窗口的起始位置?. {1 B# Y. ~8 _- Q5 |
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了
8 v* A5 i& t5 _# N1 }1 y3 P3 Z* m如何移动窗口的结束位置?* K) e& y$ V2 D/ r- R
窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
- g9 b: }' b \, T+ Y- o: `$ L# J- k6 T7 j! p. X7 O
代码如下# c6 u/ B1 ]% f5 k
2 |( v8 j' ?5 \! |" ]class Solution {7 z* p( ]: t1 Z& B4 x p) ]! X
public:
; C% J0 A5 _% K/ U6 Y4 ]1 I int minSubArrayLen(int s, vector<int>& nums) {
2 U, P7 H, ?, R3 M/ V8 Z int result = INT32_MAX;" B8 |- b& g+ q) l" E( g
int sum = 0; // 滑动窗口数值之和
5 x5 @& _. C, ~1 R) ` int i = 0; // 滑动窗口起始位置
, |( \% x# r) y+ ~- l( X9 n int subLength = 0; // 滑动窗口的长度% l" g3 J; V& F
for (int j = 0; j < nums.size(); j++) {. P* Y; [, p8 {$ } h
sum += nums[j];
3 [) P! a% K p% q+ U // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件1 F0 ]& \- l* |- H
while (sum >= s) {; K7 R1 }( W, O$ E! Y
subLength = (j - i + 1); // 取子序列的长度
8 o, | a; [" |$ |! q; R result = result < subLength ? result : subLength;//一定会赋值5 \5 D" j( ^* v, u# I
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
3 f& J! E6 D5 t }
# O! b7 b. L0 s3 { }% @4 `2 P" q2 R! S3 s# _' v# V- Z
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列/ D5 S7 l% ~/ U J( f! v
return result == INT32_MAX ? 0 : result;
7 o. B( x$ _+ X) p! J' E- L* _( F }
* y! s$ Q8 b9 r4 K5 k/ E};
1 I4 T& S6 _' t) R5 Y' R8 A; t* s5 S+ {/ ^4 N
一旦大于,就减去左区间的值) i2 ~+ T* h: H: ]- M
, [' z7 u9 u L# l6 a3 H
5.最难题螺旋矩阵||. u8 f& k4 b& g$ F
模拟顺时针画矩阵的过程:6 I* |; Q8 _5 T9 ^
7 u9 c9 {% i; q& r; \9 y8 K" S: B
填充上行从左到右5 a' ]" e9 K- s
填充右列从上到下. b( j1 e5 y. Y% I0 C' d
填充下行从右到左
; q0 u3 X3 N5 g填充左列从下到上1 ], L4 V7 t8 X! D* k
由外向内一圈一圈这么画下去。# b& {4 w H5 _' @% q
9 Q7 H$ L* S$ \5 i: Z' C这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。" I$ [ ~& o& e% D8 F6 y$ M
4 Z6 T) B! o b1 C$ v7 K( O
7 r2 L7 |. C) y4 S* f9 x4 A
/ m1 O9 B& b) @* z$ [6 Z4 ^# ^3 Q: X! k) g9 o2 r6 b4 g; j
4 B0 \2 y- x: ^7 {- x0 Q% E+ d
class Solution {: C& @3 |) G0 Z' z/ N; K# p2 C) Z
public:( s/ `. V" d6 N3 ?
vector<vector<int>> generateMatrix(int n) {" r/ j$ Q& q& s5 ]0 ~- |* o* _
vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组 o8 ~1 a+ N" j( F
int startx = 0, starty = 0; // 定义每循环一个圈的起始位置1 Z8 X5 h; |& q
int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理1 a1 L& |3 ?5 J/ s, c6 c
int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
3 `& C; j3 n8 F3 o4 z9 ` int count = 1; // 用来给矩阵中每一个空格赋值
, c, r' ?8 P; w& o" x int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位& x9 N! h. Z( B( z! p
int i,j;
9 k% j0 X7 ?4 g* s while (loop --) {
/ x# h3 R: i: n9 R$ q8 a0 ? i = startx;0 v" T( }8 Z- M* X
j = starty;
, u$ e; V! {/ g2 h( d! o* c) n- H& \1 G# v* |6 z6 J: }
// 下面开始的四个for就是模拟转了一圈0 g" `2 `$ z- Q$ i
// 模拟填充上行从左到右(左闭右开)2 R+ F5 m$ C2 I1 {, ~
for (j = starty; j < n - offset; j++) {% |& R% T) w9 `4 F) W N5 W
res[startx][j] = count++;
# J8 y0 z0 D- ^) ` }
$ e' C8 O0 j0 n // 模拟填充右列从上到下(左闭右开)
" \2 H# ~% f# H2 H/ w2 A5 p for (i = startx; i < n - offset; i++) {, K& e- Q6 d7 ~- D8 }: P! i3 R
res[j] = count++;9 h! c5 J8 K6 A, x2 L& X$ D0 D- |
}, x8 A6 I" O3 a
// 模拟填充下行从右到左(左闭右开)! g" x9 A" j5 l% S5 S; C
for (; j > starty; j--) {" a8 {1 A4 h+ }7 f$ s, f
res[j] = count++;9 j k+ W6 P$ K4 k. Q' I
}* H5 s2 h' E' A( E4 y; c5 D0 V
// 模拟填充左列从下到上(左闭右开)" v: o: B K- x! e( S4 i9 e# [. P5 J
for (; i > startx; i--) {
% B6 l( T9 s6 a! H$ A0 C, ? res[j] = count++;1 k' {/ `% _, P! h8 a) ]0 ?
}; {6 V% r0 k9 y0 {
c9 e8 V; l/ b1 a0 [
// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
$ I2 I# k, P3 g startx++;
" V: O* U7 x6 M starty++;: o( k( k: Q6 P
, {4 s: J1 m) [7 b* d) K // offset 控制每一圈里每一条边遍历的长度* t& x4 b, |# s$ F8 F
offset += 1;
# X' s. T0 X J0 u( o+ G }
, c" e: V" M I
& @7 f4 K5 z7 Q // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值4 \ Z0 P( p% c% x
if (n % 2) {
) q3 s# c; u, U& s res[mid][mid] = count;! j5 M% w- E! W) r3 o
}
+ I" H4 g1 R- h return res;3 K% M' H7 S1 W4 f# D& }- u
}5 c ?. i/ [* N
};
9 A+ v2 Q! t0 s/ @2 c- Q" _$ G E4 M
————————————————
/ _6 ^0 j) T3 T版权声明:本文为CSDN博主「编程界的谢菲尔德」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
/ M( n; G9 ~- S' R原文链接:https://blog.csdn.net/qq_62309585/article/details/126745039
+ l( U8 @3 L, _$ _( l! j' P
# ~9 I7 G& P& S' s( ?! N1 K) h: o6 Q
|
zan
|