LeetCode,TOP100面试高频,附思路(十五)

大家好,我是方圆
无它,唯手熟尔

题号

    • 1. 两数之和
    • 2. 两数相加
    • 3. 无重复字符的最长子串
    • 5. 最长回文子串
    • 6. Z字形变换


1. 两数之和

LeetCode,TOP100面试高频,附思路(十五)_第1张图片

  • 思路
    用Map存数,将与map中的值进行包含判断,包含就返回结果
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement)) {
                return new int[] { map.get(complement), i };
            }
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }

}

2. 两数相加

LeetCode,TOP100面试高频,附思路(十五)_第2张图片

  • 思路
    1.两数相加,我第一时间脑子闪过的就是进制,所以不要忘了进制,尤其是循环完成后最后一位的进制
    2.每轮相加完成后,l1和l2指针的移动一位
    3.创建预先指针,用来返回结果
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        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 == 1) {
            cur.next = new ListNode(carry);
        }
        return pre.next;
    }
}

3. 无重复字符的最长子串

LeetCode,TOP100面试高频,附思路(十五)_第3张图片

  • 思路
    1.我第一反应是滑动窗口双指针问题
    2.用Map对字符和索引进行存储,防止重复
    3.在不重的情况下,end指针后移,ans为end-start+1,这一点很容易想到
    4.我觉得比较难的地方在,出现重复的时候,怎么让start指针移动,它移动的位置应该为出现重复的字符的(已经存在map中)后一位
    5.但是为什么要用Math.max()函数,大家可以考虑一下abba这种特殊情况,当第二次重复a时,它不应该移动到第一个a的后一位,而是当前start位置不动
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        HashMap<Character,Integer> map = new HashMap<>();
       
        if(n == 0){
            return 0;
        }          
        for(int start = 0,end = 0;end < n;end++){
            char c = s.charAt(end);
            if(map.containsKey(c)){
                start = Math.max(start,map.get(c) + 1);
            }
            map.put(c,end);

            ans = Math.max(ans,end - start + 1);
        }
        
        return ans;
    }
}

5. 最长回文子串

LeetCode,TOP100面试高频,附思路(十五)_第4张图片

  • 思路
    1.这个问题一看就是动态规划问题,为什么这么说呢?首先它是求最值问题,答案很多,需要找出最优子结构子问题有重叠
    2.那该如何解决这道题,长度为0,1的一定为回文串,剩下的需要我们用动态规划,自底向上判断,创建dp[][]二维数组,使用它的上半部分,其中对角线部分为整条字符串的字符分布,单个字符都为回文串,都为true,dp[i][j],则表示起始坐标为i,终止坐标为j的字符串是否为回文串
    3.状态转移方程比较简单,看代码即可理解
class Solution {
    public String longestPalindrome(String s) {
        //特殊情况,单个字符时直接返回回文串
        int len = s.length();
        if(len < 2){
            return s;
        }

        //用来保存最大长度和初始位置
        int maxLen = 1;
        int begin = 0;
        //用二维数组对角线上半部分保存是否为回文串
        boolean[][] dp = new boolean[len][len];
        char[] charArray = s.toCharArray();

        for(int i = 0;i < len;i++){
            //对角线为单字符,全部为true
            dp[i][i] = true;
        }

        //开始动态规划
        for(int j = 1;j < len;j++){
            for(int i = 0;i < j;i++){
                if(charArray[i] != charArray[j]){
                    dp[i][j] = false;
                }else{
                    //这种情况是首位相同、长度为2或为3的情况
                    if(j - i < 3){
                        dp[i][j] = true;
                    }else{
                        //长度较长的时候,判断它的字串是不是回文串
                        //若字串是回文串,那么就是;否则,反之
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                //当出现回文串的时候,便进行判断,是否需要记录长度
                if(dp[i][j] && j - i + 1 > maxLen){
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }

        return s.substring(begin,begin + maxLen);
    }
}

6. Z字形变换

LeetCode,TOP100面试高频,附思路(十五)_第5张图片

  • 思路
    1.Z形最少为2行,为1时为原字符串
    2.创建String数组,用它来存储每行都是什么字符,它的行数为字符串长度和z形长度中的最小值
    3.down表示是否向下走,loc表示要为哪行字符串添加值
class Solution {
    public String convert(String s, int numRows) {
        if(numRows == 1)
            return s;
        
        int len = Math.min(s.length(), numRows);
        String []rows = new String[len];
        for(int i = 0; i< len; i++) rows[i] = "";
        int loc = 0;
        boolean down = false;

        for(int i=0;i<s.length();i++) {
            rows[loc] += s.substring(i,i+1);
            if(loc == 0 || loc == numRows - 1)
                down = !down;
            loc += down ? 1 : -1;
        }
        
        String ans = "";
        for(String row : rows) {
            ans += row;
        }
        return ans;
    }
}

加油,多写多练呐

你可能感兴趣的:(LeetCode)