第一题
493. 翻转对
这道题我们采用分治的思想,通过单调性和双指针的策略来解决:
策略一:
我们通过递归将每一个分的左区域和右区域变成降序排列,最后在同一层的左右区域进行判断,当前数组为降序时,固定每一个左指针的数,移动右指针,当左指针的一半小于右指针所指的数时,右指针继续右移;当左指针的一半大于右指针所指的数时,由于降序数组的单调性可知,当前右指针右边的所有的元素都满足我们的题目所求,所以计算当前右指针右边所右元素的个数;
同时移动左指针,接着循环,直到找出所有的满足题目的元素个数;
策略二:
我们通过递归将每一个分的左区域和右区域变成降序排列,最后在同一层的左右区域进行判断,当前数组为升序时,固定每一个右指针的数,移动左指针,当左指针的一半小于右指针所指的数时,左指针继续右移;当左指针的一半大于右指针所指的数时,由于升序数组的单调性可知,当前左指针右边的所有的元素都满足我们的题目所求,所以计算当前左指针右边所有元素的个数;
同时移动右指针,接着循环,直到找出所有的满足题目的元素个数;
代码如下:
class Solution { int[] tmp; public int reversePairs(int[] nums) { int n = nums.length; tmp = new int[n]; return mergeSort(nums,0,n-1); } public int mergeSort(int[] nums,int left,int right){ if(left >= right) return 0; int mid = (left+right)/2,ret = 0; //[left,mid],[mid+1,right]; //去求左右 两边的翻转对 ret +=mergeSort(nums,left,mid); ret +=mergeSort(nums,mid+1,right ); //处理一左一右,先计算翻转对 int cur1 = left,cur2 = mid+1,i=left; //降序 while(cur1 <= mid){ while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) {cur2++;} if(cur2 >right){ break; } ret += right -cur2 + 1; cur1++; } //合并两个有序数组 cur1 = left;cur2 = mid+1; while(cur1 <= mid && cur2 <= right){ tmp[i++] = nums[cur1] <=nums[cur2]?nums[cur2++]:nums[cur1++]; } while(cur1 <= mid) tmp[i++] = nums[cur1++]; while(cur2 <= right) tmp[i++] = nums[cur2++]; for(int j = left;j<= right;j++){ nums[j] = tmp[j]; } return ret; } }
第二题
2. 两数相加
题意如下所示:
上述两个链表分别为两个整数的每一个位数上的数字并逆序,最后要求我们求出两个整数相加后的结果并逆序输出;如下所示:
我们模拟两数相加的过程;
第一步:
第二步:
t因为是两位数,所以只取个位数;
第三步:
由于t依旧是两位数,所以两位依旧取个位数
综上所述,代码如下:
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode cur1 = l1,cur2 = l2; ListNode newHead = new ListNode(0);//创建一个虚拟头结点,方便记录结果 ListNode prev = newHead;//尾插操作的尾指针 int t = 0; while(cur1 != null || cur2 != null ||t != 0){ //先加上第一个链表 if(cur1 != null){ t +=cur1.val; cur1 = cur1.next; } //加上第二个链表 if(cur2 != null){ t +=cur2.val; cur2 = cur2.next; } prev.next = new ListNode(t%10); prev= prev.next; t /= 10; } return newHead.next; } }
ps:本次的内容就到这里了,如果大家感兴趣的话就请一键三连哦!!!