【每日三题】2022-3-21 LeetCode 4-6

4. 寻找两个正序数组的中位数

思路:暴力解法,merge两个数组并找中位数。实际我们可以省去merge过程,通过双指针模拟merge找到中位数。因为两个数组都是正序数组,所以从头开始遍历两个数组,将小的那一个去除,同时后移指针并减小计数。直至找到中间的数字。单数长度数组的中位数索引是length / 2,而双数长度数组的中位数索引是length / 2 - 1,与length / 2的两个数字的平均值。

代码:

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    if (nums1.length == 0 && nums2.length == 0) {
        return 0;
    }
    int i1 = 0, i2 = 0, index = (nums1.length + nums2.length) / 2;
    boolean isEven = (nums1.length + nums2.length) % 2 == 0;
    double result = 0;
    while (index >= 0) {
        int temp;
        if (i1 >= nums1.length) {
            temp = nums2[i2];
            i2 ++;
            index --;
        } else if (i2 >= nums2.length) {
            temp = nums1[i1];
            i1 ++;
            index --;
        } else {
            if (nums1[i1] > nums2[i2]) {
                temp = nums2[i2];
                i2 ++;
                index --;
            } else {
                temp = nums1[i1];
                i1 ++;
                index --;
            }
        }
        if ((isEven && index == 0) || index == -1) {
            result += temp;
        }
    }
    return isEven ? result / 2 : result;
}

时间复杂度:O(N)

空间复杂度:O(1)

5. 最长回文子串

思路:回文字符串都有回文中心,从头遍历字符串,以每一个位置(长度为奇数)以及每一个间隔(长度为偶数)作为回文中心,向两边延伸,得到可能的回文子串,记录下最长的。

代码:

public String longestPalindrome(String s) {
    if (s == null || s.length() <= 0) {
        return "";
    }
    int start = 0, end = 0;
    for (int i = 0 ; i < s.length(); i++) {
        int len1 = expandFromCenter(s, i, i);
        int len2 = expandFromCenter(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 expandFromCenter(String s, int left, int right) {
    while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
        left --;
        right ++;
    }
    return right - left - 1;
}

时间复杂度:O(N2)

空间复杂度:O(1)

6. Z字型变换

思路:找规律,发现每个Z的间隔为 (n - 1) * 2,记为space。每一行中两个数的间隔都是有规律的。除了第一行和最后一行外,每个Z都包含两个间隔。遍历每行,取i作为行号,左边的间隔为space - 2 * i,右边的间隔为 2 * i。同时发现这个间隔对第一行和最后一行也适用,不过要注意第一行的右边间隔为0,而最后一行的左边间隔为0。找到了规律后,我们开始逐行读取。使用StringBuilder / char[] 作为结果缓冲区,遍历每行。每行的一个字符的下标为i,然后左右间隔交替推进,若间隔不为0,则将指针更新到推进后的位置,同时将字符放入缓冲区。最后遍历完成后,依照缓冲区内容返回结果。

代码:

public String convert(String s, int numRows) {
    if (s == null || s.length() <= 0) {
        return "";
    }
    if (numRows == 1 || numRows > s.length()) {
        return s;
    }
    StringBuilder sb = new StringBuilder();
    int space = (numRows - 1) * 2;
    for (int i = 0; i < numRows; i++) {
        int space1 = space - 2 * i, space2 = space - space1;
        int j = i;
        sb.append(s.charAt(j));
        while (j < s.length()) {
            if (space1 != 0) {
                j += space1;
                if (j < s.length()) {
                    sb.append(s.charAt(j));
                }
            }
            if (space2 != 0) {
                j += space2;
                if (j < s.length()) {
                    sb.append(s.charAt(j));
                }
            }
        }
    }
    return sb.toString();
}

时间复杂度:O(N)

空间复杂度:O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值