算法训练Day2

28 阅读2分钟

image.png

package com.gientech.iomp;

class Solution {

    public String longestPalindrome(String s) {
        if (s == null || s.length() < 2) {
            return s == null ? "" : s;
        }

        int start = 0;
        int end = 0;

        for (int i = 0; i < s.length(); i++) {
            // 奇数长度
            int len1 = expandAroundCenter(s, i, i);
            // 偶数长度
            int len2 = expandAroundCenter(s, i, i + 1);
            int len = Math.max(len1, len2);

            if (len > end - start + 1) {
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }

        return s.substring(start, end + 1);
    }

    private int expandAroundCenter(String s, int left, int right) {
        int l = left;
        int r = right;
        // 扩展,直到不能扩展为止
        while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
            l--;
            r++;
        }
        // 扩展结束后真实长度
        return r - l - 1;
    }

}

解题思路:使用中心扩展法

中心扩展法

  • 回文串的本质:从中间向两边对称

  • 回文中心分两种:

    1. 奇数长度aba → 中心是一个字符
    2. 偶数长度abba → 中心是两个字符之间

所以:

  • 枚举每一个位置 i

  • 尝试:

    • i, i(奇数回文)
    • i, i+1(偶数回文)
  • 以该中心不断向左右扩展,得到以该中心为基准的最长回文长度

  • 取所有中心中的最大值

image.png

class Solution {
public void merge(int\[] nums1, int m, int\[] nums2, int n) {
// 初始化指针 i, j 分别指向 nums1 和 nums2 的有效部分末尾
// k 指向 nums1 的末尾(预留空间的最后一格)
int i = m - 1;
int j = n - 1;
int k = m + n - 1;

        // 从后往前合并,比较 nums1 和 nums2 当前末尾的元素
        while (i >= 0 && j >= 0) {
            if (nums1[i] > nums2[j]) {
                // nums1 当前元素较大,放入末尾
                nums1[k--] = nums1[i--];
            } else {
                // nums2 当前元素较大,放入末尾
                nums1[k--] = nums2[j--];
            }
        }

        // 如果 nums2 还有剩余元素,拷贝到 nums1 的前面空位
        while (j >= 0) {
            nums1[k--] = nums2[j--];
        }
        // 不需要处理 nums1 剩余部分,因为它们已经在正确位置上
    }

}```

解题思路:

nums1 后面有足够空间\
从数组末尾开始比较\
每次把较大的数放到 nums1 的最后\
指针向前移动,直到合并完成