day18

第一题

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:本次的内容就到这里了,如果大家感兴趣的话就请一键三连哦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值