912. 排序数组
归并排序:
class Solution {
int tmp[];
public int[] sortArray(int[] nums) {
tmp=new int[nums.length];
mergeSort(nums, 0, nums.length-1);
return nums;
}
//归并排序
//1.将数组分为两半,分别对两边的数组进行排序
//2.对合并的数组进行归并操作
public void mergeSort(int[] nums, int l, int r){
if(l>=r) return;
int mid=l+(r-l)/2;
//对左右两边分别进行归并排序
mergeSort(nums,l,mid);
mergeSort(nums,mid+1,r);
//排序完成之后执行将两边合并
merge(nums,l,mid,r);
}
//合并操作
public void merge(int[] nums, int l, int mid, int r){
int i=l,j=mid+1,k=l;
while(i<=mid && j<=r){
if(nums[i]<=nums[j]){
tmp[k++]=nums[i++];
}else{
tmp[k++]=nums[j++];
}
}
while(i<=mid) tmp[k++]=nums[i++];
while(j<=r) tmp[k++]=nums[j++];
for(int m=l;m<=r;++m){
nums[m]=tmp[m];
}
}
}
25. K 个一组翻转链表
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
//pre指向待翻转链表的前驱,end指向待反转链表的最后一个节点,start指向待反转链表的头节点,next指向end的下一个节点。
//若要求不足k个也反转,则在end查找第k个节点时,for语句里的判断条件改为end.next!=null,同时将break语句删除。
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
//首先设置一个伪头节点,令pre/end同时指向它
ListNode dummy=new ListNode(0,head);
ListNode pre=dummy;
ListNode end=dummy;
while(end.next!=null){
//循环k次,令end指向待反转链表的最后一个节点,若end==null代表不足k个节点,直接跳出循环
for(int i=0; i<k && end!=null; ++i){
end=end.next;
}
if(end==null) break;
//start节点指向待反转链表的头节点
ListNode start=pre.next;
//next指向end的下一个节点
ListNode next=end.next;
//令end节点与后面的链表断开,方便反转
end.next=null;
//将链表反转,并令前驱节点的next等于反转后的(部分)链表首节点
pre.next=reverseNode(start);
//将反转链表与将要反转的链表相连接
start.next=next;
//令pre和end指向已反转链表的尾部
pre=start;
end=start;
}
return dummy.next;
}
//反转链表
public ListNode reverseNode(ListNode head){
ListNode pre=null;
ListNode cur=head;
while(cur!=null){
ListNode next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
}
15. 三数之和
代码:
//解题思路
//1.排序
//2.固定第一个节点,设置两个指针分别指向第一个节点之后的首尾节点,使用双指针法寻找与第一个节点和为0的两个节点。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res=new LinkedList<>();
Arrays.sort(nums);
//至少要留出两个位置给i和j
for(int k=0; k<nums.length-2; ++k){
//当k指向节点大于0时,ij指向的节点必然大于0,跳出循环
if(nums[k]>0) break;
//当k指向节点与前一个节点相同时,k继续遍历下一个节点,因为nums[k]所对应的满足条件的三元组已经全部加入res中
if(k>0 && nums[k]==nums[k-1]) continue;
//i,j分别指向首尾
int i=k+1, j=nums.length-1;
while(i<j){
int sum=nums[i]+nums[j]+nums[k];
//1.当和为0时,将i,j,k指向元素添加到res中,i,j分别指向下一个值不相同的节点
//2.当和小于0时,i指向下一个值不相同的节点
//3.当和大于0时,j指向下一个值不相同的节点
if(sum==0){
res.add(new ArrayList<Integer>(Arrays.asList(nums[i],nums[j],nums[k])));
while(i<j && nums[i]==nums[++i]);
while(i<j && nums[j]==nums[--j]);
}else if(sum<0){
while(i<j && nums[i]==nums[++i]);
}else{
while(i<j && nums[j]==nums[--j]);
}
}
}
return res;
}
}
160. 相交链表
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
//假设相交前A链表有a个节点,B链表有b个节点,相交后有c个节点。
//分别设置两个指针遍历A,B链表,走到尾部时指向另一个链表头,则经过a+b+c步后两个指针必然同时指向交点。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pA=headA, pB=headB;
while(pA!=pB){
pA= pA==null?headB : pA.next;
pB= pB==null?headA : pB.next;
}
return pA;
}
}