例题1: 两数之和
这题可以用双指针法和hashmap做。
用双指针做的话需要额外的时间开销是排序O(nlogn),需要注意点:
-
返回的是原本数组的下标而非排序后数组的下标,所以要加一个遍历搜下标的方法getPos
-
上述方法要注意数组中存在多个一样的数的情况,比如:
[3,3] 6
可以自己选择合适的方法避免这类情况。
代码如下:
class Solution { public int[] twoSum(int[] nums, int target) { if(nums.length<2) return null; int left; int right; int[] result=new int[2]; //new一个数组进行排序 int[] sort=new int[nums.length]; System.arraycopy(nums,0,sort,0,nums.length); Arrays.sort(sort); for(left=0,right=sort.length-1;left<right; ){ int temp=sort[left]+sort[right]; if(temp==target){ result=getPos(nums,sort,left,right); return result; } if(temp<target)left++; if(temp>target)right--; } return null; } public int[] getPos(int[] nums,int[] sort,int left,int right){ int[] result=new int[]{-1,-1}; for(int i=0;i<nums.length;i++){ if(nums[i]==sort[left] && result[0]==-1) { result[0]=i; }else if(nums[i]==sort[right]) { result[1]=i; } } return result; }}
执行用时:2 ms, 在所有 Java 提交中击败了99.60%的用户
内存消耗:40 MB, 在所有 Java 提交中击败了44.31%的用户
例题2:面试题 02.01. 移除重复节点
使用临时缓冲区的方法比较简单,比如采用hashmap然后通过是否存在key来移除或者保留节点,时间复杂度为O(n)。用双指针法就是两重循环,时间复杂度高,适合要求不采用临时缓冲区的方法,实现代码如下:
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
//单向节点,只能从前到后遍历
if(head==null || head.next == null)return head;
ListNode node=head;
//要考虑改变head节点的next节点
ListNode headNext=null;
while(node!=null){
ListNode next=node;
while(next.next!=null){
if(next.next.val==node.val){
next.next=next.next.next;
}else{
next=next.next; }
}
node=node.next;
}
return head;
}
}
要注意的是:
1.用node指向head之后,head.next不会因为循环而改变,所以需要一个node保存循环后head.next应该指向的值,否则{1,1,1,1,1,2}这类的数组输出结果是{1,1,2}。所以要从head开始判断,而不是直接从head.next开始判断和head是否一致(适用于所有单向链表);
2.删除的时候需要一个变量保存前节点来删除节点,要分析好next和next.next在值相等的时候指向哪里,不相等又指向哪里。
这是牺牲时间换空间的方法,所以执行用时就很不行。
执行用时:405 ms, 在所有 Java 提交中击败了6.11%的用户
内存消耗:40.7 MB, 在所有 Java 提交中击败了77.27%的用户
例题3: 977. 有序数组的平方
class Solution {
public int[] sortedSquares(int[] A) {
//双数组法从两边到中间
int left;
int right;
int[] squares=new int[A.length];
int i;
for(left=0,right=A.length-1,i=A.length-1;left<=right && i>=0;i--){
int l=(int)Math.pow(A[left],2);
int r=(int)Math.pow(A[right],2);
if(l>r){
squares[i]=l;
left++;
}else{
squares[i]=r;
right--;
}
}
return squares;
}
}
例题4:1300. 转变数组后最接近目标值的数组和
class Solution {public int findBestValue(int[] arr, int target) { Arrays.sort(arr); int sum = 0; int ave = target / arr.length; if (arr[0] > ave) { double aveDou = (target * 1.0) / arr.length; System.out.println(aveDou); if (Math.abs(aveDou - ave) <= 0.5) { return ave; } else { return ave + 1; } } for (int i = 0; i < arr.length - 1; i++) { sum += arr[i]; int curAve = (target - sum) / (arr.length - i - 1); System.out.println("curAvue"+curAve); System.out.println("i"+i); if (curAve < arr[i + 1]) { double curAveDou = (target * 1.0 - sum) / (arr.length - i - 1); System.out.println(curAveDou); if (Math.abs(curAve - curAveDou) <= 0.5) { return curAve; } else { return (curAve + 1); } } } return arr[arr.length - 1]; }}