初级题目
数组问题
从排序数组中删除重复项
1 | int removeDuplicates(vector<int>& nums) { |
买卖股票的最佳时机
解读
典型的贪心算法,当明天比今天低价的时候将股票卖出即可。
代码
1
2
3
4
5
6
7
8
9
10int maxProfit(vector<int>& prices) {
int result = 0;
for(int i = 0; i < prices.size() - 1; i++){
if( prices[i] < prices[i + 1]){
result = result + (prices[i + 1] - prices[i]);
}
}
return result;
}
旋转数组
给定一个数组,将数组中的元素向右移k位,其中k是非负数
说明
- 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 要求使用空间复杂度为 O(1) 的原地算法。
解读
参考这篇博客使用
i = (i + k) % n
的思路,每次调换元素后,后一个元素调换都是基于上一个位置。如:1
1,2,3,4,5,6,7,8 n = 8, k = 2
则执行流程如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30//奇数位旋转完毕
1
1,2,3,4,5,6,7,8
3
1,2,1,4,5,6,7,8
5
1,2,1,4,3,6,7,8
7
1,2,1,4,3,6,5,8
7,2,1,4,3,6,5,8
//偶数位旋转开始
2
7,2,1,4,3,6,5,8
4
7,2,1,2,3,6,5,8
6
7,2,1,2,3,4,5,8
8
7,2,1,2,3,4,5,6
7,8,1,2,3,6,5,6解题如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33class Solution
{
public:
void rotate(vector<int> &nums, int k)
{
if (nums.size() == 0 || (k %= nums.size()) == 0)
{
return;
}
int length = nums.size();
int start = 0;
int i = 0;
int cur = nums[i];
int cnt = 0;
gengxin
while (cnt++ < length)
{
i = (i + k) % length;
int t = nums[i]; //t用于记录转换前的数字
nums[i] = cur; //旋转
if (i == start) //用于处理奇偶位旋转问题
{
++start; //start更新
++i; //index更新
cur = nums[i]; //因为更新了奇偶位,用于转换的数据也需要更新
}
else
{
cur = t; //将上一次被转换的位置的数据用于转换下次数据
}
}
}
};
存在重复
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
1
2输入: [1,2,3,1]
输出: true解读
- 可以利用set的特性来解决这个问题
- 可先排序,然后再判断是否有连续index具备相同的元素
解题如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
bool flag = false;
set<int> set_int;
for(int i = 0; i < nums.size(); i++){
set_int.insert(nums[i]);
}
if(set_int.size() != nums.size()){
flag = true;
}
return flag;
}
};只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
1
2输入: [2,2,1]
输出: 1解读
两个相同的数字进行异或后得到0
解题如下
1
2
3
4
5
6
7
8
9
10
11class Solution {
public:
int singleNumber(vector<int>& nums) {
int tmp = 0;
for(int i = 0; i < nums.size(); i++){
tmp = tmp ^ nums[i];
}
return tmp;
}
};
两个数组的交集 II
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
1
2输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]说明:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
进阶:

搜索
20:03
一家子
未来 如果给定的数组已经排好序呢?你将如何优化你的算法?如果 nums1 的大小比 nums2 小很多,哪种方法更优?
如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
解读
可以使用map的特性,值对具备相同性质的元素进行筛选,利用
value
记录元素出现的次数解题如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
map<int, int> num2count1;
vector<int> result;
for(int i = 0;i < nums1.size(); i++){
if(num2count1.find(nums1[i]) != num2count1.end()){
num2count1[nums1[i]]++;//每出现一次+1
}else{
num2count1[nums1[i]] = 1;//初次出现则初始化value
}
}
for(int i = 0; i < nums2.size(); i++){
if(num2count1.find(nums2[i]) != num2count1.end()){
result.push_back(nums2[i]);
num2count1[nums2[i]]--;//将一个元素放入result
if(num2count1[nums2[i]] == 0) num2count1.erase(num2count1.find(nums2[i]));//如果元素被放置完,则删除该元素
}
}
return result;
}
};
开始
1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
1 | 给定 nums = [2, 7, 11, 15], target = 9 |
两遍哈希表法
1 | class Solution { |
一遍哈希表
1 | class Solution { |
3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
第一种解法 滑动窗口解法
时间复杂度:O(n^2)
空间复杂度:O(1)
1 | class Solution { |
第二种解法 hashmap优化
时间复杂度:O(n^2)
空间复杂度:O(n^2)
1 | class Solution { |
利用hashmap记录的字符位置信息,节约缩窄窗口左侧的时间,达到以空间换时间的目的。
5. 最长回文字符串
使用动态规划的方法
时间复杂度:O(n^2)
空间复杂度:O(n^2)
1 |
|
6. Z 字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING"
行数为 3 时,排列如下:
1 | L C I R |
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"
。
请你实现这个将字符串进行指定行数变换的函数:
1 | string convert(string s, int numRows); |
示例 1:
1 | 输入: s = "LEETCODEISHIRING", numRows = 3 |
题解
- 初始化字符串数组用于记录字符排列顺序
- 自上往下,再自下往上对字符进行逐个排列
- 利用flag判断排列方向,初始化为-1
- 当到达灵界点,即最上层和最下层时,改变排列方向,flag:-1 —> 1—> -1
- 最后遍历所有字符串,并进行拼接
1 | class Solution { |