双指针法
删除排序数组中的重复项
一个快指针,一个慢指针。
易错点:
考虑空数组
什么时候快指针++,什么时候慢指针++。
动态规划
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0||prices==null){
return 0;
}
int maxprofit = 0;
int minprice = Integer.MAX_VALUE;
//循环一遍,一边更新最小值,一边更新最大利润。
for(int i = 0;i<prices.length;i++){
if(prices[i]<minprice){
minprice=prices[i];
}else if(prices[i]-minprice>maxprofit) {
maxprofit=prices[i]-minprice;
}
}
return maxprofit;
}
}
贪心算法
三种方法:
- 暴力递归
- 反转数组(妙啊)
- 环状替代
循环不变式
三种方法:
- 循环不变式(超时)
在下一次搜索之前,搜索过的整数中没有重复的整数。
时间复杂度 : O(n^2)O(n 2 )。最坏的情况下,需要检查 \frac{n(n+1)}{2} 2n(n+1)对整数。因此,时间复杂度为 O(n^2)O(n2)。
空间复杂度 : O(1)O(1)。只使用了常数额外空间。
class Solution {
public boolean containsDuplicate(int[] nums) {
for(int i =0;i<nums.length;i++){
for(int j =0;j<i;j++){
if(nums[j]==nums[i]){
return true;
}
}
}
return false;
}
}
- 排序
排序使重复元素相邻。
时间复杂度 : O(nlogn)
空间复杂度: O(1)
class Solution {
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
for(int i=0;i<nums.length-1;++i){
if(nums[i]==nums[i+1]){
return true;
}
}
return false;
}
}
- 哈希表
快速插入和搜索的数据结构,利用HashSet的不可重复性。
可以利用add方法的返回值来判断,时间快一些。
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>(nums.length);
for(int x:nums){
if(!set.add(x)){
return true;
}
}
return false;
}
}
下面利用contains方法,先判断,再加。时间长一些。
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> set = new HashSet<>(nums.length);
for(int x:nums){
if(set.contains(x)) return true;
set.add(x);
}
return false;
}
}
只出现一次的数字
暴力循环
class Solution {
public int singleNumber(int[] nums) {
for(int i =0;i<nums.length;i++){
for(int j =0;j<nums.length;j++){
if(nums[j]==nums[i]&&i!=j) break;
if(j==nums.length-1) return nums[i];
}
}
return 0;
}
}
排序再查找(分对,一对一对找)
class Solution {
public int singleNumber(int[] nums) {
Arrays.sort(nums);
for(int i = 0;i<nums.length-1;i+=2){
//相等的话就继续,不等的话左边为落单的
if(nums[i]!=nums[i+1]) return nums[i];
}
//代码执行到这说明前面都是成对的数,则最后一个为只出现一次的数
return nums[nums.length-1];
}
}