• LeetCode中等题(三)


    题目一:

    反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

    说明:
    1 ≤ m ≤ n ≤ 链表长度。

    示例:

    输入: 1->2->3->4->5->NULL, m = 2, n = 4
    输出: 1->4->3->2->5->NULL

    方法一:

    1、和链表反转很相似,增加了难度,需要选择一定的区间

    2、找到区间进行反转,最后再将链表和之前的进行连接

    3、首先找到反转链表的前一位,for(int i=0;i<m-1;i++) pre=pre.next;

    4、然后开始反转链表,定义两个结点,ListNode node=null,ListNode curr=pre.next;然后进行循环链表反转,循环条件直到i<n-m+1

    5、最后将链表进行连接,pre.next.next=curr,pre.next=node;

    6、返回哑结点dummy.next

    具体代码:

    class Solution {
        public ListNode reverseBetween(ListNode head, int m, int n) {
            
            ListNode dummy=new ListNode(0);
            dummy.next=head;
            ListNode pre=dummy;
            
            for(int i=0;i<m-1;i++) pre=pre.next;
            
            ListNode node=null;
            ListNode curr=pre.next;
            
            for(int i=0;i<n-m+1;i++)
            {
                ListNode temp=curr.next;
                curr.next=node;
                node=curr;
                curr=temp;
            }
            
            pre.next.next=curr;
            pre.next=node;
            
            return dummy.next;
        }
    }

    题目二:

    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

    例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

    与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

    方法:

    1、要求三个数和目标值进行比较,采用三次循环的时间复杂度相对较高,设置双指针和一个循环进行比较

    2、双指针设置在第一层循环里,当然需要先对数组进行排序,Arrays.sort(nums);

    3、ans=nums[0]+nums[1]+nums[2],设置返回的初始值;

    4、for(int i=0;i<nums.length;i++) int start=i+1,end=nums.lenght-1,int sum=nums[i]+nums[start]+nums[end];

    5、while(start<end) ,这一点较为关键比较目标值和sum之间的距离,取最小值

    6、if(Math.abs(target-sum)<Math.abs(target-ans)) ans=sum

    7、移动双指针,直到遍历完所有的情况,if(target<sum) start++;if(target>sum) end--;

    8、返回ans;

    具体代码:

    class Solution {
        public int threeSumClosest(int[] nums, int target) {
            
            Arrays.sort(nums);
            int ans=nums[0]+nums[1]+nums[2];
            
            for(int i=0;i<nums.length;i++)
            {
                int start=i+1,end=nums.length-1;
                while(start<end)
                {
                    int sum=nums[i]+nums[start]+nums[end];
                    if(Math.abs(target-sum)<Math.abs(target-ans))
                    {
                        ans=sum;
                    }
                    if(sum>target)
                        end--;
                    else if (sum<target) {
                        start++;
                    }
                    else {
                        return ans;
                    }
                }
            }        
            return ans;
        }
    }

    题目三:

    给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    注意:
    不能使用代码库中的排序函数来解决这道题。

    示例:

    输入: [2,0,2,1,1,0]
    输出: [0,0,1,1,2,2]

    方法:

    1、这其实是一个排序问题,思路也不是很容易想到;

    2、这里面可以用三指针实现一个指向数组最开始,一个指向数组最末尾,另一进行逐个遍历数组

    3、思想较为巧妙,p0指向0的最右端,p2指向2的最左端,curr进行遍历数组

    4、通过交换元素和指针移动进行

    具体代码:

    class Solution {
        public void sortColors(int[] nums) {
            
            int p0=0,p2=nums.length-1;
            int curr=0;
            
            for(int i=0;i<nums.length;i++)
            {
                if(nums[curr]==0)
                {
                    int temp=nums[curr];
                    nums[curr++]=nums[p0];
                    nums[p0++]=temp;
                }
                else if (nums[curr]==2)
                {
                    int tem=nums[curr];
                    nums[curr]=nums[p2];
                    nums[p2--]=tem;
                }
                
                else {
                    curr++;
                }
            }
        }
    }

    题目四:

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

    说明:解集不能包含重复的子集。

    示例:

    输入: nums = [1,2,3]
    输出:
    [
    [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]

    方法一:

    1、递归+回溯实现,这个方法代码很简洁,但却很不好理解;

    2、递归是在一个循环中进行,也就是在循环中进行循环

    3、进行深度优先遍历将所有在一个值的情况,然后再进行回溯

    4、回溯的时候一定要去除数组的最上面的元素

    具体代码:

    class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            
            List<List<Integer>> res=new ArrayList<>();
            backTrace(0,nums,res,new ArrayList<Integer>());
            return res;
        }
        
        public void backTrace(int i,int[] nums,List<List<Integer>> res,ArrayList<Integer> tem)
        {
            res.add(new ArrayList<>(tem));
            for(int j=i;j<nums.length;j++)
            {
                tem.add(nums[j]);
                backTrace(j+1, nums, res, tem);
                tem.remove(tem.size()-1);
            }       
        }
    }

    题目五:

    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

    candidates 中的数字可以无限制重复被选取。

    说明:

    所有数字(包括 target)都是正整数。
    解集不能包含重复的组合。 
    示例 1:

    输入: candidates = [2,3,6,7], target = 7,
    所求解集为:
    [
    [7],
    [2,2,3]
    ]

    方法:

    1、回溯+递归,仍然采用上式的方式;

    2、不同点在于要求得的列表是不同的,之前是求子集,而现在求满足符合目标元素的值;

    3、只要满足目标值,就将此数组加入到res中

    4、算法的回溯是根据目标值,而不是下一个元素,因为元素可以重复使用

    具体代码:

    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            
            List<List<Integer>> res=new ArrayList<>();
            Arrays.sort(candidates);
            backdown(candidates,target,0,res,new ArrayList<>());
            return res;
        }
        
        public void backdown(int[] candidates,int target,int i,List<List<Integer>> res,ArrayList<Integer> temp)
        {
            if(target<0) return;
            if(target==0)
            {
                res.add(new ArrayList<>(temp));
                return;
            }
            
            for(int j=i;j<candidates.length;j++)
            {
                if(target<candidates[j]) break;
                temp.add(candidates[j]);
                backdown(candidates,target-candidates[j],j,res,temp);
                temp.remove(temp.size()-1);
            }
        }
    }

    题目六:

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

    说明:解集不能包含重复的子集。

    示例:

    输入: nums = [1,2,3]
    输出:
    [
    [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]

    方法:

    1、这是一种很巧妙的方法,采用位运算求子集

    2、因为一个数组的子集刚好是2的n次方,比如数组元素为[1,2,3],它的子集刚好是8个,用二进制表示其大小n=1<<3;

    3、然后将这8个子集分别放入列表中,接下来是如何放入列表的问题;

    4、对这8个数进行循环,for(int i=0;i<8;i++)  for(int j=0;j<3;j++) 将i进行位运算,找到所有为1的数值,将其加入到temp中;

    5、if(i>>j&1==1) list.add(nums[j]);

    具体代码:

    class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            
            List<List<Integer>> res=new ArrayList<>();
            int n=1<<nums.length;
            
            for(int i=0;i<n;i++)
            {
                List<Integer> list=new ArrayList<>();
                for(int j=0;j<nums.length;j++)
                {
                    if(((i>>j)&1)==1)
                        list.add(nums[j]);
                }
                
                res.add(list);
            }        
            return res;
        }  
    }

    题目七:

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

    说明:

    你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

    示例 1:

    输入: [2,2,1]
    输出: 1

    方法:

    1、异或运算,同假异真

    2、异或的性质,0^一个数=这个数,数一^数一=0,并且满足交换律和结合律

    具体代码

    class Solution {
        public int singleNumber(int[] nums) {
            
            int result=0;        
            for(int i=0;i<nums.length;i++)
            {
                result=result^nums[i];
            }       
            return result;
        }
    }

    题目八:

    给定一个整数,编写一个函数来判断它是否是 2 的幂次方。

    示例 1:

    输入: 1
    输出: true
    解释: 20 = 1

    方法:

    1、采用位运算,对整数n进行与运算,如果n是2的幂次方,那么n&n-1=0

    具体代码:

    class Solution {
        public boolean isPowerOfTwo(int n) {
            if((n>0)&&(n&(n-1))==0)
                return true;
            else
            {
                return false;
            }
        }
    }
  • 相关阅读:
    go语言基本语法
    go语言学习
    Dockerfile简单实战
    Dockerfile构建命令
    docker安装prometheus grafana监控
    docker kali安装及复现永恒之蓝漏洞
    Windows系统实用快捷键
    python pip修改国内源
    网络基础——子网掩码及网络划分
    OSI七层模型简单概念及相关面试题
  • 原文地址:https://www.cnblogs.com/Optimism/p/11437001.html
Copyright © 2020-2023  润新知