leetcode-热题100之2.3.5.11.15 [Java]

题目2.

2. 两数相加https://leetcode.cn/problems/add-two-numbers/

 

想法:从头节点开始,对应位置相加,注意保存进位,累加到下一个节点;注意每次连接新节点都要新创建节点,最高位若有进位需额外创建一个节点。

代码:

/**
 * 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; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode res = new ListNode(); //只是一个节点,后续节点还需要创建
        ListNode cur = res;
        int carry = 0;
        while(l1!=null||l2!=null){
            int x = l1 == null ? 0 : l1.val;
            int y = l2 == null ? 0 : l2.val;
            int sum = x+y+carry; 

            carry = sum/10;
            sum = sum%10;
            cur.next = new ListNode(sum);

            cur = cur.next;
            if(l1 != null)
                l1 = l1.next;
            if(l2 != null)
                l2 = l2.next;
        }
        if(carry > 0) {
            cur.next = new ListNode(carry);
        }
        return res.next;
    }
}

结果:

题目3: 

3. 无重复字符的最长子串https://leetcode.cn/problems/longest-substring-without-repeating-characters/

想法:借助hashmap;遍历字符串,将字符存入hashmap;如果该字符已存在,则比较当前len和i-j的大小;若不存在,则直接len++。

代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character,Integer> map = new HashMap<>();
        int len=0,res=0;
        for(int i=0;i<s.length();i++){
            char c=s.charAt(i);
            if(map.containsKey(c)){
                int j=map.get(c);
                len=len<(i-j)?len+1:i-j;
            }
            else
                len++;
            res=Math.max(res,len); //最大长度
            map.put(c,i);
        }
        return res;
    }
}

结果:

题目5:

5. 最长回文子串https://leetcode.cn/problems/longest-palindromic-substring/

想法:动态规划。如果bab是回文,那么cbabc也是回文;则需要一个数组记录子串是否回文,再寻找最长长度;因最终需要返回回文子串,注意记录回文子串的起始位置。

我们用一个 boolean dp[l][r] 表示字符串从 i 到 j 这段是否为回文。

试想如果 dp[l][r]=true,我们要判断 dp[l-1][r+1] 是否为回文,及在(l-1)和(r+1)两个位置是否为相同的字符,便会减少很多重复计算。

初始状态,l=r 时,此时 dp[l][r]=true。
状态转移方程,dp[l][r]=true 并且(l-1)和(r+1)两个位置为相同的字符,此时 dp[l-1][r+1]=true。

代码:

class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len<2)
            return s;
        int start=0;
        int max=1;//最长回文串的长度

        boolean[][] dp = new boolean[len][len];//dp数组

        for(int r=1;r<len;r++){
            for(int l=0;l<len;l++){
                if(s.charAt(r)==s.charAt(l) && (r-l<=2||dp[l+1][r-1]) ){
                    dp[l][r]=true;
                    if(r-l+1>max){
                        max=r-l+1;
                        start=l;
                    }
                }
            }
        }
        return s.substring(start,start+max);
    }
}

结果:

题目11:

11. 盛最多水的容器https://leetcode.cn/problems/container-with-most-water/

 

 想法:本题为计算索引差和短边形成的长方形面积最大值。使用双指针法

在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 -1−1​ 变短:

若向内 移动短板 ,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 可能变大,因此下个水槽的面积可能增大 。
若向内 移动长板 ,水槽的短板 min(h[i], h[j])min(h[i],h[j])​ 不变或变小,因此下个水槽的面积 一定变小 。


因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。

代码:

class Solution {
    public int maxArea(int[] height) {
        int i=0,j=height.length-1;
        int max=0,tmp=0;
        while(i<j){
            if(height[i]<height[j]){
                tmp=height[i]*(j-i);
                i++;
            }
            else{
                tmp=height[j]*(j-i);
                j--;
            }
            max=max>tmp?max:tmp;
        }
        return max;
    }
}

结果:

题目15:

15. 三数之和https://leetcode.cn/problems/3sum/

 想法:先排序,排序后从左端开始遍历,先得到a=nums[i],再在后面使用双指针法寻找bc之和为-nums[i],注意跳过重复元素。

代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2)
        List<List<Integer>> res = new ArrayList<>();
        if(nums.length<3)
            return res;
        Arrays.sort(nums);// O(nlogn) 排序

        for(int i=0;i<nums.length-2;i++){// O(n^2)
            if(nums[i]>0)// 第一个数大于 0,后面的数都比它大,肯定不成立了
                break;
            if(i>0 && nums[i]==nums[i-1])// 去掉重复情况
                continue;
            int target = -nums[i];// 定一个找两个,下面是双指针
            int left=i+1,right=nums.length-1;
            while(left<right){
                if(nums[left]+nums[right]==target){
                    res.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
                    // 首先无论如何先要进行加减操作
                    left++;
                    right--;
                    while(left<right && nums[left]==nums[left-1])// 左边去重
                        left++;
                    while(left<right && nums[right]==nums[right+1])// 右边去重
                        right--;
                }else if(nums[left]+nums[right]>target){
                    right--;
                }else{ // nums[left]+nums[right]<target
                    left++;
                }
            }
        }
        return res;
    }
}

结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值