LeetCode01-05

01-两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

package LeetCodeHot100;

import java.util.*;

public class L01TwoNumSum {
    /**
     * 使用hashmap
     * 由题目得不存在重复的答案
     * @param nums
     * @param target
     * @return
     */
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map = new HashMap<>();
        for (int i=0;i< nums.length;i++){
            if (map.containsKey(target-nums[i])){
                //map在以第一个
                return new int[]{map.get(target-nums[i]),i};
            }else {
                map.put(nums[i], i);
            }
        }
        throw new IllegalArgumentException("没有数相加等于target");
    }
}

02-两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

package LeetCodeHot100;

public class L02LinkNodeTwoNumSum {
    /**
     * 将两个链表看成是相同长度的进行遍历,如果一个链表较短则在前面补 0,
     * 比如 987 + 23 = 987 + 023 = 1010
     * 每一位计算的同时需要考虑上一位的进位问题,而当前位计算结束后同样需要更新进位值
     * 如果两个链表全部遍历完毕后,进位值为 1,则在新链表最前方添加节点1

     * 对于链表问题,返回结果为头结点时,通常需要先初始化一个预先指针 pre,
     * 该指针的下一个节点指向真正的头结点head。
     * 使用预先指针的目的在于链表初始化时无可用节点值,
     * 而且链表构造过程需要指针移动,进而会导致头指针丢失,无法返回结果。
     * @param l1
     * @param l2
     * @return
     */
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //预设节点,防止移动过程中头指针丢失
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        int carry = 0;
        while (l1!=null||l2!=null){
            //当l1或者l2为空时,补0
            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 = cur.next;
            if (l1!=null) l1=l1.next;
            if (l2!=null) l2 =l2.next;
        }
        //如果最高位有进位
        if (carry==1){
            cur.next = new ListNode(carry);
        }
        return pre.next;
    }
}

03-无重复字符串的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

package LeetCodeHot100;

import java.util.HashMap;
import java.util.Map;

public class L03NoRepeatString {
    /**
     * 滑动窗口
     * 定义一个 map 数据结构存储 (k, v),其中 key 值为字符,
     * value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重复
     * 我们定义不重复子串的开始位置为 start,结束位置为 end
     * 随着 end 不断向后遍历,会遇到与 [start, end] 区间内字符相同的情况,
     * 此时将字符作为 key 值,获取其 value 值,并更新 start,此时 [start, end] 区间内不存在重复字符
     * 无论是否更新 start,都会更新其 map 数据结构和结果 max。

     * @param s
     * @return
     */
    public int lengthOfLongestSubstring(String s) {
        int length = s.length();
        int max = 0;

        Map<Character,Integer> map = new HashMap<>();
        for (int start = 0,end =0;end<length;end++){
            char element = s.charAt(end);
            if (map.containsKey(element)){
                //map.get()的地方进行+1操作
                //存在就更新start的位置
                //这里取start的最大值的原因是,如果后面两个字母重复的话,不取最大值可能会导致start回退
                //如 a.. b..a...a...b
                //当到第二个a的时候,start=3,下一步到第二个b,如果start = map.get(b)+1 = 2 ,可见start由3回退到2了
                start = Math.max(map.get(element)+1,start);
            }
            //更新最大不重复字符串的值
            max = Math.max(max,end-start+1);
            //放入最新的字符
            map.put(element,end);
        }
        return max;
    }
}

04-

暂无

05-最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。
示例 2:

输入:s = “cbbd” 输出:“bb”

根据状态表理解

package LeetCodeHot100;

public class L05LongestPalindrome {
    /**
     * 动态规划的状态转移方程:
     * dP(i, j) = dP(i+1, j-1)∧ (S_i == S_j)
     * 也就是说,只有s[i+1:j−1] 是回文串,
     * 并且 s 的第 i 和 j 个字母相同 s[i:j] 才会是回文串
     * 上文的所有讨论是建立在子串长度大于 2 的前提之上的,我们还需要考虑
     * 动态规划中的边界条件,即子串的长度为 1 或 2。对于长度为 1 的子串,
     * 它显然是个回文串;对于长度为 2 的子串,只要它的两个字母相同,它就是一个回文串。
     *边界条件:
     * dP(i,i)=true
     * dP(i,i+1)=(Si==Si+1)
     * 最终的答案即为所有dP(i,j)=true 中 j-i+1(即子串长度)的最大值
     * @param s
     * @return
     */
//------------------------------------------------------------------------------
    //dp[i][j]表示当前子字符串,i到j是否是回文字符串::
    //状态转移方程式::dp[i][j] = dp[i+1][j-1]&&(ch[i]==ch[j])
    //边界条件 由状态转移方程,,子字符串至少需要三个字符:
       // 只有一个字符 dp[i][i] = true,,两个字符::dp[i][i+1] = ch[i]==ch[i+1]
    public String longestPalindrome(String s) {
        if(s==null||s.length()==0) return "";
        if(s.length()==1) return s;
        char[] ch = s.toCharArray();
        int len = ch.length;
        int[] ans = new int[2];
        boolean[][] dp = new boolean[len][len];
        int maxlength = 1;
        //j相当于右边界,每次求子串[0,j]的最长回文子串
        for(int j=0;j<len;j++){
            for(int i=0;i<j;i++){
                //包含了边界处理
                dp[i][j] = (ch[i]==ch[j])&&(j-i<3||dp[i+1][j-1]);
                //如果此子区间是回文串,则看是否更长,是则更新
                if(dp[i][j]&&maxlength<j-i+1){
                    maxlength = j-i+1;
                    ans[0] = i;
                    ans[1] = j;
                }
            }
        }
        return s.substring(ans[0],ans[1]+1);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值