LeetCode第4,5题

第4题

题目:寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays

想法:

如果不涉及时间复杂度的要求的话,就可以类似于归并排序中,将两个有序数组进行归并的步骤,用python中的列表来模拟的操作,进行归并
时间复杂度为O(m+n),但是根据中位数的特性,可以省去大约一半的归并工作,实际O((m+n)/2)

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        whole_list = []
        len1 = len(nums1)
        len2 = len(nums2)
        num = len1 + len2
        i = 0
        if num % 2 == 0:
            median_max = num/2
        else:
            median_max = (num-1)/2
        while(i <= median_max):
            if nums1 == []:
                whole_list.append(nums2[0])
                nums2.pop(0)
            elif nums2 == []:
                whole_list.append(nums1[0])
                nums1.pop(0)
            elif nums1[0] < nums2[0]:   #比较栈顶元素大小
                whole_list.append(nums1[0])
                nums1.pop(0)
            elif nums2[0] <= nums1[0]:
                whole_list.append(nums2[0])
                nums2.pop(0)
            i += 1
        if num % 2 == 0:
            print(whole_list)
            return float((whole_list[int(median_max)] + whole_list[int(median_max)-1]))/2
        else:
            return whole_list[int(median_max)]

想法2:

既然要求时间复杂度为O(log2(m+n))那肯定是要用到二分查找的方式,考虑到中位数的特性,参考了网上的代码,实现了对于切分的二分查找。

#include <stdio.h>
#include <vector>
using namespace std;

#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))

class Solution {
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
		int n = nums1.size();
		int m = nums2.size();

		if (n > m)  //保证数组1一定最短
		{
			return findMedianSortedArrays(nums2, nums1);
		}

		// Ci 为第i个数组的割,比如C1为2时表示第1个数组只有2个元素。LMaxi为第i个数组割后的左元素。RMini为第i个数组割后的右元素。
		int LMax1, LMax2, RMin1, RMin2, c1, c2, lo = 0, hi = 2 * n;  //我们目前是虚拟加了'#'所以数组12*n长度

		while (lo <= hi)   //二分
		{
			c1 = (lo + hi) / 2;  //c1是二分的结果
			c2 = m + n - c1;

			LMax1 = (c1 == 0) ? INT_MIN : nums1[(c1 - 1) / 2];
			RMin1 = (c1 == 2 * n) ? INT_MAX : nums1[c1 / 2];
			LMax2 = (c2 == 0) ? INT_MIN : nums2[(c2 - 1) / 2];
			RMin2 = (c2 == 2 * m) ? INT_MAX : nums2[c2 / 2];

			if (LMax1 > RMin2)
				hi = c1 - 1;
			else if (LMax2 > RMin1)
				lo = c1 + 1;
			else
				break;
		}
		return (max(LMax1, LMax2) + min(RMin1, RMin2)) / 2.0;
	}
};

第5题:

题目:最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring

想法:

回文串的意义无非就是正着和倒着读是相同的,那其实最小的回文子串应该有两种形态

  1. 两个字符为一个单位的 例如:bb
  2. 三个字符为一个单位的 例如:aba
    不论是哪种最短回文子串,向两端发散(例如 看cabac的最短回文子串单元aba的左边一个字符是否跟右边一个字符相等)来找到以该回文子串为中心,能够获得多长的回文子串,不断迭代就可找到最长的回文子串。

特殊情况:当一个串即时第1种,又是第2种时,例如:bbbb 那干脆把两种都找到进行搜索

所以现在要做的就是在字符串s中,找到这两种的最小回文子串单元,然后分别向两端发散找到最大的回文子串 时间复杂度Omax(N2)

class Solution:
    def longestPalindrome(self, s: str) -> str:
        i = 0
        longest_str = ""
        if len(s) == 1:
            return s
        elif len(s) == 0:
            return ""
        while(i < len(s)-1):    #首先为滑动窗口为3 / 2的窗口向前移动
            if s[i-1] == s[i+1] and i-1 >= 0: #当滑动窗口长度为3
                string = self.JudgeLongestPalindrome3(i,s)
                print(string)
                if len(longest_str) <= len(string):
                    longest_str = string
            if s[i] == s[i+1]:#找到回文子串最小单元
                string = self.JudgeLongestPalindrome2(i,s)
                print(string)
                if len(longest_str) <= len(string):
                    longest_str = string
            i += 1
        if longest_str == "":
            return s[0]
        return longest_str
    def JudgeLongestPalindrome3(self,i,s):
        for j in range(1,1000):
            if i-j-1 < 0 or i+j+1 > len(s)-1:
                return s[i-j:i+j+1]
            elif s[i-j-1] == s[i+j+1]:
                continue
            else:
                return s[i-j:i+j+1]
    def JudgeLongestPalindrome2(self,i,s):
        for j in range(1,1000):
            if i-j < 0 or i+j+1 > len(s)-1:
                return s[i-j+1:i+j+1]
            elif s[i-j] == s[i+j+1]:
                continue
            else:
                return s[i-j+1:i+j+1]
if __name__ == "__main__":
    s1 = Solution()
    s = "abababababababababababababa"
    print(s1.longestPalindrome(s))

随记就到这里啦~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值