当前位置 博文首页 > weixin_34111819的博客:第一篇博文,leetcode3道题

    weixin_34111819的博客:第一篇博文,leetcode3道题

    作者:[db:作者] 时间:2021-08-15 13:36

    ?LeetCode做题笔记

    ?

    1. Add two numbers:给定一个数集合和一个数,已知集合中有两个数的和是给定数,求这两个加数的index

    方法1:暴力,n^2时间复杂度,不推荐

    方法2:快速排序nlogn。按集合里数的两倍与target的大小关系对分。对每一个第一部分的数,在另外一个部分二分搜索第二个数:500~ms

    方法3hashn的时间复杂度,最高纪录420ms

    方法3源码:

    /*
    ?*?Method?2nd
    
    public?void?swap(int?i,?int?j,?int[]?array)?{
    ????int?temp?=?array[i];
    ????array[i]?=?array[j];
    ????array[j]?=?temp;
    }
    
    public?final?Random?RANDOM_INT?=?new?Random();
    private?int?getRondomIndex(int?left,?int?right)?{
    ????return?RANDOM_INT.nextInt(right?-?left)?+?left;
    }
    public?int?partition(int?left,?int?right,?int?array[]){
    ????if?(left?==?right){
    ????????return?left;
    ????}
    ????//randomized?quicksort
    ????swap(right,?getRondomIndex(left,?right),?array);
    ????int?i?=?left;
    ????int?j?=?right?-?1;
    ????int?partitioner?=?array[right];
    ????//i?=?j?must?be?executed
    ????while?(i?<=?j){
    ????????//check?boundary?first
    ????????while?(i?<=?right?-?1?&&?array[i]?<=?partitioner)
    ????????????i++;
    ????????while?(j?>=?0?&&?array[j]?>=?partitioner)
    ????????????j--;
    ????????if?(i?<?j)
    ????????????swap(i,?j,?array);
    ????}
    ????if?(i?<?right)
    ????????swap(right,?i,?array);
    ????return?i?<?right?-?1???i?:?right?-?1;
    }
    
    public?void?quickSort(int?left,?int?right,?int[]?array){
    ????if?(right?<=?left){
    ????????return;
    ????}
    ????//first?partition,?then?quick?sort
    ????int?q?=?partition(left,?right,?array);
    ????quickSort(left,?q,?array);
    ????quickSort(q?+?1,?right,?array);
    }
    
    public?int[]?twoSum(int[]?numbers,?int?target)?{
    ????//index?Map
    ????Map<Integer,?List<Integer>>?indexMap?=?new?HashMap<>();
    ????int?numCount?=?numbers.length;
    ????int[]?result?=?new?int[2];
    ????//hash?value?and?indices
    ????for?(int?i?=?0;?i?<?numbers.length;?i++){
    ????????if?(indexMap.get(numbers[i])?==?null)
    ????????????indexMap.put(numbers[i],?new?ArrayList<Integer>());
    ????????indexMap.get(numbers[i]).add(i);
    ????}
    ????for?(List<Integer>?list?:?indexMap.values()){
    ????????if?(list.size()?>?1){
    ????????????//Duplicate?value:?
    ????????????//1.?2?*?value?=?target
    ????????????//2.?[exactly?one?answer]?->?no?possibility?to?be?answer
    ????????????if?(numbers[list.get(0)]?*?2?!=?target){
    ????????????????for?(Integer?integer?:?list){
    ????????????????????//Set?these?integers?to?be?null
    ????????????????????numbers[integer]?=?Integer.MAX_VALUE;
    ????????????????}
    ????????????????numCount?-=?list.size();?
    ????????????}
    ????????????else?return?new?int[]{list.get(0)?+?1,?list.get(1)?+?1};
    ????????}
    ????}
    ????
    ????quickSort(0,?numbers.length?-?1,?numbers);
    ????int?boundary?=?getBounder(numCount,?target,?numbers);
    ????for?(int?i?=?0;?i?<?boundary;?i++){
    ????????int?temp?=?binary_search(i,?numCount?-?1,?target?-?numbers[i],?numbers);
    ????????if?(temp?!=?-1){
    ????????????int?int1?=?indexMap.get(numbers[i]).get(0)?+?1;
    ????????????int?int2?=?indexMap.get(numbers[temp]).get(0)?+?1;
    ????????????if?(int1?>?int2)
    ????????????????return?new?int[]?{int2,?int1};
    ????????????else?{
    ????????????????return?new?int[]?{int1,?int2};
    ????????????}
    ????????}
    ????}
    ????
    ????return?null;
    }
    
    public?int?getBounder(int?numCount,?int?target,?int[]?numbers){
    ????int?i;
    ????for?(i?=?0;?i?<?numCount;?i++){
    ????????if?(2?*?numbers[i]?>?target)
    ????????????break;
    ????}
    ????return?i;
    }
    
    public?int?binary_search(int?left,?int?right,?int?key,?int[]?numbers){
    ????int?mid?=?(left?+?right)?/?2;
    ????if?(right?<?left)
    ????????return?-1;
    ????if?(numbers[mid]?==?key)
    ????????return?mid;
    ????if?(numbers[mid]?>?key)
    ????????return?binary_search(left,?mid?-?1,?key,?numbers);
    ????else?{
    ????????return?binary_search(mid?+?1,?right,?key,?numbers);
    ????}
    }*/
    
    public?int[]?twoSum(int[]?numbers,?int?target)?{??
    
    ????HashMap<Integer,?Integer>?map?=?new?HashMap<Integer,?Integer>();??
    ????int?n?=?numbers.length;??
    ????int[]?result?=?new?int[2];??
    ????for?(int?i?=?0;?i?<?numbers.length;?i++)??
    ????{??
    ????????if?(map.containsKey(target?-?numbers[i]))?{??
    ????????????result[0]?=?map.get(target-numbers[i])?+?1;??
    ????????????result[1]?=?i?+?1;??
    ????????????break;??
    ????????}??
    ????????else?{??
    ????????????map.put(numbers[i],?i);??
    ????????}??
    ????}??
    ????return?result;??
    }

    经验1:对hashMapgetput都是非常耗时间的,尽量少做

    经验2:方法2最好使用随机化快排,效率很高

    ?

    ?

    把两个链表表示的数加起来:最佳624ms3%, (LeetCode 2, medium)

    用长一点的链表做基础,最多只需要new一个新节点

    优化建议:进位尽量用数字。如果一个链到头了,另一个没到,应该沿着长链前进。如果进位是0就可以即刻返回,不需要继续前进。

    源码:

    public?ListNode?addTwoNumbers(ListNode?l1,?ListNode?l2)?{
    ????int?sum,?progress?=?0;
    ????ListNode?tmp1?=?l1,?tmp2?=?l2;
    ????for?(;;){
    ????????sum?=?l1.val?+?l2.val?+?progress;
    ????????progress?=?sum?>=?10???1?:?0;
    ????????
    ????????l1.val?=?l2.val?=?sum?>=?10???sum?-?10?:?sum;
    ????????if?(l1.next?==?null){
    ????????????if?(l2.next?==?null){
    ????????????????if?(progress?==?1)
    ????????????????????l2.next?=?new?ListNode(1);
    ????????????????return?tmp2;
    ????????????}
    ????????????else?{
    ????????????????l2?=?l2.next;
    ????????????}
    ????????????for?(;?;){
    ????????????????if?(progress?==?0)
    ????????????????????return?tmp2;
    ????????????????sum?=?l2.val?+?1;
    ????????????????progress?=?sum?>=?10???1?:?0;
    ????????????????l2.val?=?sum?>=?10???0?:?sum;
    ????????????????
    ????????????????if?(l2.next?==?null){
    ????????????????????if?(progress?==?1)
    ????????????????????????l2.next?=?new?ListNode(1);
    ????????????????????break;
    ????????????????}
    ????????????????else
    ????????????????????l2?=?l2.next;
    ????????????}
    ????????????return?tmp2;
    ????????}
    ????????if?(l2.next?==?null){
    ????????????l1?=?l1.next;
    ????????????for?(;?;){
    ????????????????if?(progress?==?0)
    ????????????????????return?tmp1;
    ????????????????sum?=?l1.val?+?1;
    ????????????????progress?=?sum?>=?10???1?:?0;
    ????????????????l1.val?=?sum?>=?10???sum?-?10?:?sum;
    
    ????????????????if?(l1.next?==?null){
    ????????????????????if?(progress?==?1)
    ????????????????????????l1.next?=?new?ListNode(1);
    ????????????????????break;
    ????????????????}
    ????????????????else
    ????????????????????l1?=?l1.next;
    ????????????}
    ????????????return?tmp1;
    ????????}
    ????????l1?=?l1.next;?
    ????????l2?=?l2.next;
    ????????????
    ????}
    }

    经验2leetcode不靠谱啊,速度不一定对

    ?

    把一个整数数位逆转,注意符号,不能溢出

    最好记录404ms,前5%


    public?static?int?reverse(int?x)?{
    ????StringBuilder?string?=?new?StringBuilder(x?+?"");
    ????int?flag?=?1;
    ????if?(string.charAt(0)?==?'-'){
    ????????flag?=?-1;
    ????????string.reverse().deleteCharAt(string.length()-1);
    ????????
    ????}
    ????else?{
    ????????string.reverse();
    ????}
    ????try{
    ????????return?flag?==?1???Integer.parseInt(string.toString())?:?-1?*Integer.parseInt(string.toString());
    ????}
    ????catch?(Exception?e){
    ????????return?0;
    ????}
    }

    经验3:类库比较快。而且好像早上/×××以后机器运算比较快?


    官方提示:

    To check for overflow/underflow, we could checkif ret > 214748364 or ret < –214748364 before multiplying by 10. On theother hand, we do not need to check if ret == 214748364, why? 溢出是214748364721474836410不溢出


    cs