链表和数组的高频面试题
数组高频面试题
No.1(LeetCode1:两个数之和)
题:给定一个非负整数的数组,给定一个target,如果数组中有两个元素相加的和等于target,那么返回这两个数的下标。
代码:本题思路,不使用暴力解法,通过使用空间换时间的方式来求解
public class Solution{
public int [] twoSum(int [] nums,int target){
// 构建缓存器,用来存储nums中的数据。
Map<Integer,Integer> cache = new HashMap();
for(int i = 0;i<nums.length;i++){
// 判断缓存中是否有另一半
if(cache.containsKey(target-nums[i])){
return new int[]{cache.get(target-nums[i]),i}
}else{
cache.put(nums[i],i);
}
}
return null;
}
}
思路分析:此题用的思想就是用空间来替换运行时间,遍历整个数组以后,在数组寻找target-nums[i]这个数,如果找到了,返回这两个数在数组中的下标,如果没有找到,则将i下标的数存入缓存器中,妙啊!
No.2(leetCode15:三数之和)
题:给定一个包含N个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0?,找出所有和为0且不重复的三元组。
思路:使用三指针思想,定义三指针i,j,k,这里用的一个比较重要的思想就是剪枝,就是一开始就过滤到一些不满足题目意思的案例,这个题目我打算手写一遍,加深一下代码印象和理解程度。
public class Solution{
public List<List<Integer>> threeNumberSum(int arr[]){
// 首先进行数组的长度和非空判断
if(arr == null || arr.length<3){
// 直接返回一个空的集合
return new ArrayList();
}
// 排序数组
Arrays.sort(arr);
// 定义存储集合的集合
List<List<Integer>> res = new ArrayList();
// 循环遍历
for(int i = 0;i<arr.length<2;i++){
// 去重第一步,如果i下标走到i+1的位置发现下标对应的数相等
if(i>0&& arr[i]==arr[i-1]){
continue;
}
// 条件判断
if(arr[i]>0){
break;
}
// 定义三指针了
int j = i+1;
int k = arr.length-1;
while(j<k){
int a = arr[i];
int b = arr[j];
int c = arr[k];
// 判断三个数之和是否为0
if((a+b+c)==0){
// 定义集合来存三个数
List<Integer> list = new ArrayList();
list.add(a);
list.add(b);
list.add(c);
// 在循环外定义好存储集合的集合
res.add(list);
// 添加后进一步排出重复的情况
while(j<k&&arr[j]==arr[j+1]){
j++;
}
while(j<k&&arr[k]==arr[k-1]){
k--;
}
// 排出后让指针继续走
j++;
k--;
}else if((a+b+c>0)){
// 让k指针前移,数大了。
k--;
}else{
j++;
}
}
}
// 返回最终需要的集合
return res;
}
}
总结:写了几题后发现代码思路真的很关键,是非常关键,没有思路,是根本写不出代码的!
No.3(LeetCode-LCP18寻找匹配的早餐组合)
思路:同样是先排序,利用双指针思想。
代码:
public class Solution{
public int findArray(int [] staple,int [] drinks,int x){
// 排序
Arrays.sort(staple);
Arrays.sort(drinks);
// 定义符合题目组合的变量res
int res = 0;
// 定义双指针
int i = 0;
int j = drinks.length-1;
// 判断
while(i<staple.length&&j>=0){
// 判断
if*(staple[i] + drinks[j] <= x){
res = (res+j+1)%1000000007;//取模是防止数据溢出
i++;
}else{
// 如果结果大于x说明j索引位置上的数太大了,需要让j指针往前移。
j--;
}
}
return res;
}
}
对于数组的算法练习题还有很多,写出题号,后面去LeetCode上刷。
LeetCode 88 合并两个有序数组
LeetCode 66 加一
LeetCode 9 回文数
LeetCode 18 四数之和
LeetCode 26 删除排序数组中的重复项
LeetCode 189 旋转数组 p
链表高频面试题
No.1(LeetCode 24: 两两交换链表中的节点)
给定一个链表,两两交换其中相邻的节点,并返回交换后的节点。
解题思路:
交换节点就需要在真实的链表中将链表中的值进行交换,此题解题思路亮点就是构建哨兵,考虑到要是链表中的头节点就是要交换的节点,构造一个哨兵节点,并且一开始就要记录哨兵的值,然后将哨兵这个下个节点返回,就能得到交换节点后的链表。
public class Solution{
public ListNode swapPairs(ListNode head){
// 特殊判断
if(head == null || head.next == null){
return head;
}
// 定义指针
ListNode curr = head;
ListNode prev = new ListNode(-1);
// 将哨兵指向curr指针
prev.next = curr;
// 提前记录好哨兵节点
ListNode p = prev;
// 循环开始,交换节点。
while(curr != null && curr.next != null){
ListNode next = curr.next;
ListNode next_next = next.next;
// 交换节点
next.next = curr;
prev.next = next;
curr.next = next_next;
// 节点下跳
prev = curr;
curr = next_next;
}
return p.next;
}
}