题目:https://leetcode.com/problems/single-number/
武器:利用map计算次数,线性时间。但是需要O(n)存储空间
结果:未通过
新武器:XOR操作
异或的运算方法是一个二进制运算:
1^1=0
0^0=0
1^0=1
0^1=1
两者相等为0,不等为1.
(1) a ^ b = b ^ a;
(2) (a ^ b) ^ c = a ^ (b ^ c);
(3) a ^ a = 0, a ^ 0 = a;
the ^ means XOR.
a ^ b ^ b ^ c ^ c = a ^ 0 ^ 0 = a,只有一个单个元素,所以最后异或的结果就是单个数字。
class Solution {
public int singleNumber(int[] nums) {
int result=0;
for(int i=0;i
题目:https://leetcode.com/problems/move-zeroes/
武器: 两个指针,基于交换。但是比较麻烦。简单思路是直接覆盖
结果:未通过
新武器:如果是0,没有必要交换,直接覆盖,最后空余位置直接添加0就可以。
本次用自己的解法通过:
class Solution {
public void moveZeroes(int[] nums) {
int i=0;
int j=0;
int n=nums.length;
while(i
题目:https://leetcode.com/problems/majority-element/
武器: Hashmap统计次数
结果:一次通过
题目:https://leetcode.com/problems/contains-duplicate/
武器: hashmap统计次数
结果:一次通过
题目:https://leetcode.com/problems/missing-number/
武器: hashset
结果:未通过。
思路对,忽略了这个题目中,长度就是最后一个数字这个细节。遍历数组一遍存入set,循环<=n,数组的长度,判断是否每个元素都在set中
题目:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
武器:分析结果的关键,本来用dp,没有找到转换方程。后来发现对于当前元素,找到当前最小值,两者相减法,就是最大利润。如果是负数,max后取0也实用。当时应该是参考别人的算法写的,这次自己分析问题能力的确提高很多
结果:超过预期通过
题目:https://leetcode.com/problems/two-sum/
武器: HashMap(二次,一次都可以,最好写成一次),另一个武器,for循环过程中其实就是二分查找问题,先排序,然后for循环,寻找另外一个元素。或者排序后两个指针一个头,一个尾部,计算和,根据和与target的关系,移动low或者high,因为有序,我们可以这么做
新修改:两次for循环不可以,因为如果有重复元素,map会覆盖,所以就是一次for循环,放入元素和位置,下面继续判断left是否存在,如果存在就返回两个索引,这样即时第二个和第一个元素相同,也不会覆盖
结果:自己思考修正原来错误完美通过
题目:https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 要求空间复杂度O(1)
武器:分析移除方法,发现不同元素直接重新写入当前数组,不需要额外新建
结果:通过
题目:https://leetcode.com/problems/rotate-array/
武器:有移效果分解,其实先反转整个数组,然后反转前k个,然后反转后k个,二维矩阵也有这个方法
结果:未通过,思路没有
题目:https://leetcode.com/problems/product-of-array-except-self/
武器:除自身,因为不让用除法计算,那么可以这么理解,左侧乘积*右侧乘积=当前值除自身的乘积
结果:思路当时并没有理解透彻
题目:https://leetcode.com/problems/top-k-frequent-elements/ must be better than O(n log n)
武器:1. TreeMap排序统计频率,因为treemap可以根据频率排序,频率为key,时间复杂度不是线性的。
2. Hashmap统计频率,然后频率为value,利用桶排序就可以,新建数组,根据频率决定索引,每个数组的元素是list,负责存储改频率的所有元素,然后倒序遍历数组就是从高频到低频。利用空间换取时间。
结果:基本通过
两个注意:第一,桶排序的时候的数组的元素为list类型,第二top k最后计算的时候,相同的也算入个数,不是指不同的。
题目:https://leetcode.com/problems/4sum-ii/
武器 Hashmap
结果:思路正确,第一次把AB存入map,value是个数,开始还想用set存储,第二个CD的时候判断sum*-1在map中的个数就可以,不是判断是否存在,我思路想的是是否存在。
题目:https://leetcode.com/problems/find-the-duplicate-number/
武器: 时间复杂度优于O(n2),空间复杂度是O(1)。之前一道题目是求唯一不重复的,利用异或操作可以。因为异或操作a^a=0,b^0=b.最后异或的结果就是不重复的数字。这道题目,因为空间复杂度所以不能利用map计算,利用快速排序算法,时间复杂度满足,而且关键是空间复杂度也满足。排序后重复的数字就挨着了。
结果:通过,但是快速排序的核心代码不要直接用low和high,因为移动后,在交换轴元素和low移动后的位置的时候,已经没有轴元素的指针了,需要i=low,j=high,然后移动i和j处理就可以。另外key元素第一次是nums[0]但是递归代码里面应该是nums[low],始终是最低位元素。
快速排序代码有几个错误点,注意一下:
题目:https://leetcode.com/problems/container-with-most-water/
武器:两个指针,其实就是面积问题,max=Math.max(max,Math.min(nums[p],nums[q])*(q-p)),需要注意的是指针移动不是直接p++,q--。而是谁小移动谁,这样才能保证找到最大的。
结果:部分通过
题目:https://leetcode.com/problems/sort-colors/
武器:1.桶排序,因为只有0 1 2 三个值,但是空间复杂度不符合要求
2 快速排序
结果:通过
题目:https://leetcode.com/problems/find-peak-element/
武器:折半查找。根据时间复杂度是logn,想起来用折半,但是感觉不是有序的,不行。其实可以,因为比较条件不是是否相等,而是始终超上升的方向走,结果只有两种,第一是一直上升,第二是下降。无论那种我们都能找到一个峰值
if(nums[mid]>nums[mid+1]){
high=mid;
}
else{
low=mid+1;
}
题目:https://leetcode.com/problems/perfect-squares/
武器:动态规划,我已经成功破解关键方程 dp[i]=Math.min(dp[i-1]+1,dp[i-4]+1,dp[i-9]+1,......),一直到i的平方根。但是有点问题是我忘记了外层循环for(i=1;i<=n;i++),因为这样方程需要的中间值必须有外层循环。另外一个忽略点,dp默认都填充最大值方便进行min比较。
class Solution {
public int numSquares(int n) {
int[] dp=new int[n+1];
for(int k=1;k<=n;k++){
dp[k]=Integer.MAX_VALUE;
}
for(int i=1;i<=n;i++){
int sqrt=(int)Math.sqrt(i);
for(int j=1;j<=sqrt;j++){
dp[i]=Math.min(dp[i],1+dp[i-(j*j)]);
}
}
return dp[n];
}
}
题目:https://leetcode.com/problems/longest-increasing-subsequence/
武器:动态规划
结果:两次外层循环,因为不是一定要连续,所以dp[i]定义为小于nums[i]的元素的dp[j]最大值,注意不是小于nums[i]的元素个数,因为可能不是一直增长的。思路基本正确,注意点失误了
题目:https://leetcode.com/problems/letter-combinations-of-a-phone-number/
武器:队列LinkedList先入一个空字符串,保证while条件可以开始。然后queue负责保存中间结果,队列中取出元素与下一个组合结果,然后入队列,直到队列中peek的队首元素长度与digits长度一样,表示组合完毕。注意:mapping关系可以用数组,不需要用map
结果:思路遗忘了
String[] mapping = new String[]{"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
//添加一个空元素,保证第一个字符串入队
res.add("");
while (res.peek().length() != digits.length()) {
String removed = res.remove();
String toAddElement = mapping[digits.charAt(removed.length()) - '0'];
for (char ch : toAddElement.toCharArray()) {
res.addLast(removed + ch);
}
}
题目:https://leetcode.com/problems/course-schedule-ii/
题目:https://leetcode.com/problems/course-schedule
武器:DAG是否有环的问题。利用二维数组角度去解决。步骤如下
1. 循环数组计算各个值的入度,存入indegree数组
2 从入度为0元素开始。寻找入度为0的值加入队列。
3 循环从队列取出元素,直到队列为空。取出元素后,加入结果集,然后循环数组,判断源端是此元素的入度减去1,相当于取出这个右向链接。此时如果入度为0,加入队列
4 最后队列为空的时候,结果集的size如果为所有元素就是无环的,反之有环。