简单题
开始之前
136 只出现一次的数字
https://leetcode-cn.com/problems/single-number/
169 求众数
https://leetcode-cn.com/problems/two-sum/solution/qiu-zhong-shu-by-leetcode-2/
1 | int major = nums.length/2;//求众数的条件 |
方法一 暴力搜索法
不建议,时间复杂度O(n2),空间复杂度O(1)
1 | class Solution { |
方法二 Map遍历法
Map常用于计数方面的算法,要牢记其初始化和遍历方法
时间复杂度O(n),空间复杂度O(n)
1 | class Solution { |
方法三 Boyer-Moore 投票算法
想法: 如果我们把众数记为 +1 ,把其他数记为 -1 ,将它们全部加起来,显然和大于 0 ,从结果本身我们可以看出众数比其他数多。
(竖线用来划分每次计数器归零的情况)
[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
首先,下标为 0 的 7 被当做众数的第一个候选。在下标为 5 处,计数器会变回0 。所以下标为 6 的 5 是下一个众数的候选者。由于这个例子中 7 是真正的众数,所以通过忽略掉前面的数字,我们忽略掉了同样多数目的众数和非众数。因此, 7 仍然是剩下数字中的众数。
1 | //计数法,相同就+1;不同就-1 |
88. 合并两个有序数组
https://leetcode-cn.com/problems/merge-sorted-array/
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
1 | 输入: |
此处考虑到若从前往后 比较并排序需要把后面的数字挪动,为避免挪动增大空间复杂度,从后往前比较并填充
1 | class Solution { |
简化后
1 | public void merge(int[] nums1, int m, int[] nums2, int n) { |
字符串
125. 验证回文串
https://leetcode-cn.com/problems/valid-palindrome/
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
1 | 输入: "A man, a plan, a canal: Panama" |
示例 2:
1 | 输入: "race a car" |
双指针,一个从头开始,一个从尾开始
要求不区分大小写,就可以把字符串转为小写
一定要区分好if和while
1 | public static boolean isPalindrome(String s) { |
387. 字符串中的第一个唯一字符
https://leetcode-cn.com/problems/first-unique-character-in-a-string/
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
1 | s = "leetcode" |
方法一 Map存储遍历
和出现次数有关的,不要犹豫,hash
此类技术方法均可用map记录出现次数并遍历的方法。本题中不同点在于遍历时使用原先数组的索引进行遍历,因为题目要求的是找到第一个不重复的字符(value=1的key)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public int firstUniqChar(String s) {
Map<Character,Integer> map = new HashMap<Character, Integer>();
char[] chars = s.toCharArray();
for(char ch:chars) {
if(map.containsKey(ch)) {
map.put(ch,map.get(ch)+1);
}else {
map.put(ch,1);
}
}
for(int i=0;i<s.length();i++) {
if(map.get(chars[i]) == 1) return i;//利用字符 串索引
}
return -1;
}
方法二 桶存储
当全是字母字符时,可以考虑用大小为26的整型数组存储每个字母的频次,索引为ch-'a'
, 相当于一个简化的Map,原理与Map存储相同
此处还应注意数组初始化大小之后,整型默认值均为0
1 | public int firstUniqChar(String s) { |
344. 反转字符串
https://leetcode-cn.com/problems/reverse-string/
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
1 | 输入:["h","e","l","l","o"] |
示例 2:
1 | 输入:["H","a","n","n","a","h"] |
两个指针自增自减,相遇退出就完事了
1 | public void reverseString(char[] s) { |
数组
189. 旋转数组
https://leetcode-cn.com/problems/rotate-array/
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。要求使用空间复杂度为 O(1)的原地算法。
示例 1:
1 | 输入: [1,2,3,4,5,6,7] 和 k = 3 |
示例 2:
1 | 输入: [-1,-100,3,99] 和 k = 2 |
方法一 暴力法
理清旋转一次的算法,再重复k次即可。时间复杂度:O(n∗k) 。每个元素都被移动 1 步O(n)) k次O(k)
注意在变换时每次都是第j位和第 j-1 位的数值进行交换,并不是直接交换数值中的值,所以此处选取了prev来存储第j-1位的数值。
1 | class Solution { |
方法二 环状替换
未看
217. 存在重复元素
https://leetcode-cn.com/problems/contains-duplicate/
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
1 | 输入: [1,2,3,1] |
示例 2:
1 | 输入: [1,2,3,4] |
示例 3:
1 | 输入: [1,1,1,3,3,4,3,2,4,2] |
方法一 Map存储法
刚开始想用数组桶的方法来存储每个数字出现的频次,但这种方法就忽略了负数的情况,造成了数组越界,故仍要用map
1 | /** |
AC代码如下,也是常规map,和出现次数有关
1 | class Solution { |
Boolean数组法
没看懂
TODO
283. 移动零(TODO)
https://leetcode-cn.com/problems/move-zeroes/
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
1 | 输入: [0,1,0,3,12] |
说明: 必须在原数组上操作,不能拷贝额外的数组
参考别人的方法
1 | //思路:设置一个index,表示非0数的个数,循环遍历数组, |
最后补零的操作其实可以替代为 直接交换nums[index]和nums[i],因为index所经过的数组值都是非零项。如果是0,则index没有变,直接把i+1的非0值替换过来即可。 代码如下
1 | public void moveZeroes(int[] nums) { |
350. 两个数组的交集 II
https://leetcode-cn.com/problems/intersection-of-two-arrays-ii
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
1 | 输入: nums1 = [1,2,2,1], nums2 = [2,2] |
示例 2:
1 | 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] |
说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。可以不考虑输出结果的顺序