LeetCode50题第一天

LeetCode第2题: 两数相加

算法思路:

  1. 由于链表是从低位到高位, 我们可以逐位相加, 某一位为(l1.val + l2.val) % 10
  2. 由于存在进位问题, 需要设置一个变量作为进位, 其值为(l1.val + l2.val) // 10
  3. 如果在中途某个链表到头了, 那么就可以推出第一层循环, 循环单独的链表即可(这里可以使用将None补零, 来简化代码, 但是算法的复杂度并未简化)
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        c = 0
        #这里新创建一个链表作为结果, head为其头结点
        head = ListNode()
        mid = head
        # 第一层循环
        while l1 is not None and l2 is not None: 
            p = ListNode()
            p.val = (l1.val + l2.val + c) % 10
            c = int((l1.val + l2.val + c) / 10)
            mid.next = p
            mid = mid.next
            l1 = l1.next
            l2 = l2.next
            #第二层循环
        while l1 is not None:
            p = ListNode()
            p.val = (l1.val + c) % 10
            c = int((l1.val + c) / 10)
            mid.next = p
            mid = mid.next
            l1 = l1.next
        while l2 is not None:
            p = ListNode()
            p.val = (l2.val + c) % 10
            c = int((l2.val + c) / 10)
            mid.next = p
            mid = mid.next
            l2 = l2.next
        #防止出现高位进位
        if c == 1:
            p = ListNode(1)
            mid.next = p
        return head.next

复杂度: 设链表长度分布为m, n, 由于该算法遍历了两个链表这复杂度为O(m+n)

LeetCode第四题: 寻找两个有序数组的中位数C语言实现

解法一
  1. 先找到两个数组的长度, 然后遍历找到中位数即可
  2. 如果是奇数个, 那么就直接返回, 如果是偶数个, 那么就返回它与它前一个树的和的平均数
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int target = (nums1Size + nums2Size) >> 1;
    int i, j, pre, res;// pre记录res前边的一个数, res为返回结果
    i = j = pre = res = 0;
    // 判读跳出循环是因为一个数组到尽头了还是找到中位数了
    int flag = 0; 
    // 计数器, 找到中位数
    int count = -1;
    while (i < nums1Size && j < nums2Size) {
        pre = res;
        res = nums1[i] < nums2[j] ? nums1[i++] : nums2[j++];
        count++;
        if (count == target) {
            flag = 1;
            break;
        }
    }
    if (!flag) {
        while (count != target) {
            pre = res;
            res = (i == nums1Size) ? nums2[j++] : nums1[i++];
            count++;
        }
    }
    return (nums1Size + nums2Size) & 1 ? res * 1.0 : (pre + res) * 1.0 / 2;
}

复杂度分析: 假设两个数组长度分别为m, n, 本算法的遍历次数为(n + m) / 2, 所以复杂度为O(m + n)

解法二

算法思想:

  1. 使用二分思想
  2. 本题相当于在两个有序数组中查找中位数, 可以使用二分方法依次排除不可能的取值
  3. 假设查找值为k, 那么A[0-k/2]和B[0-k/2]绝对不会是结果, 我们可以利用这个性质, 递归求得结果
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int k, flag = 0;
    flag = (nums1Size + nums2Size) & 1;
    if (!nums1Size) return flag ? nums2[(nums2Size >> 1)] : (nums2[(nums2Size) >> 1] + nums2[((nums2Size) >> 1) - 1]) * 1.0 / 2;
    if (!nums2Size) return flag ? nums1[(nums1Size >> 1)] : (nums1[(nums1Size) >> 1] + nums1[((nums1Size) >> 1) - 1]) * 1.0 / 2;
    k = flag ? ((nums1Size + nums2Size) >> 1) + 1 : ((nums1Size + nums2Size) >> 1);
    int a1 = 0, a2 = 0;
    while (k > 1) {
        int offset = (k >> 1) - 1;
        offset = a1 + offset >= nums1Size ? nums1Size - a1 - 1 : offset;
        offset = a2 + offset >= nums2Size ? nums2Size - a2 - 1 : offset;
        a1 += offset;
        a2 += offset;
        if (nums1[a1] <= nums2[a2]) {
            a1 += 1;
            a2 -= offset;
        } else {
            a1 -= offset;
            a2 += 1;
        }
        k = k - (offset + 1);
        if (a1 >= nums1Size) return flag ? nums2[a2 + k - 1] : (nums2[a2 + k - 1] + nums2[a2 + k]) * 1.0 / 2;
        if (a2 >= nums2Size) return flag ? nums1[a1 + k - 1] : (nums1[a1 + k - 1] + nums1[a1 + k]) * 1.0 / 2;
    }
    if (flag) {
        if (a1 >= nums1Size) return nums2[a2];
        else if (a2 >= nums2Size) return nums1[a1];
        else return nums1[a1] > nums2[a2] ? nums2[a2] : nums1[a1];
    }
    
    if (nums1[a1] > nums2[a2]) {
        if (a2 + 1 >= nums2Size) return (nums1[a1] + nums2[a2]) * 1.0 / 2;
        if (nums2[a2 + 1] < nums1[a1]) return (nums2[a2] + nums2[a2 + 1]) * 1.0 / 2;
        return (nums1[a1] + nums2[a2]) * 1.0 / 2;
    } else {
        if (a1 + 1 >= nums1Size) return (nums1[a1] + nums2[a2]) * 1.0 / 2;
        if (nums1[a1 + 1] < nums2[a2]) return (nums1[a1] + nums1[a1 + 1]) * 1.0 / 2;
        return (nums1[a1] + nums2[a2]) * 1.0 / 2;
    }
}

复杂度: 假设两个数组长度为m, n, 由于使用二分查找, 复杂度为O(log(m + n))

LeetCode第5题: 寻找最长回文子串

解法一:

这个解法是我以前的代码, 具体思路如下

  1. 从最长字符开始寻找, 往短的方向寻找, 这样如果找到即可返回, 如果从最短开始, 由于不知道是否是最大的, 那么继续寻找
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if s == "":
            return ""
        if len(s) == 1:
            return s
        i = 0
        j = len(s)
        str = ""
        while len(str) < (j - i + 1):
            while len(str) < (j - i + 1):
                j = s.rfind(s[i], i, j)
                if len(str) < (j - i + 1) and s[i:j] == s[j:i:-1]:
                    str = s[i:j+1]
            j = len(s)
            i += 1
        return str

复杂度分析: 本算法相当于暴力破解, 在最好的情况需要一次, 最坏情况需要n的平方次

解法二:

马拉车算法

  1. 马拉车算法核心思想: 用过去的求过的的最长回文子串加速未知的, 本质是动态规划
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = s.replace("", "#")  # 将字符串马拉车化
        c = -1  # 初始化对称中心
        r = -1  # 初始化最小右边界
        max1 = 0  # 记录最大右边界
        cmax = c  # 记录最大边界半径
        arr = [0] * (len(s) - 1)
        # 遍历字符串
        for i in range(0, len(s) - 1):
        	# 核心加速代码: 可以直接根据i'的边界半径求出i点的在r内的边界半径
            arr[i] = min(r - i, arr[2 * c - i]) if r > i else 1 
            # 继续扩展i的边界半径
            while (i + arr[i] < len(s) and i - arr[i] > -1):
                if s[i + arr[i]] == s[i - arr[i]]:
                    arr[i] += 1
                else:
                    break
            # 如果i的边界半径大于已经记录的边界半径, 那么就更新边界半径和对称中心
            if arr[i] > max1:
                max1 = arr[i]
                cmax = i
            # 更新边界半径和对称中心
            if arr[i] + i > r:
                r = i + arr[i]
                c = i
        str = s[cmax - max1 + 1: cmax + max1 - 1]
        print(cmax, max1)
        print(str)
        return str.replace("#", "")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值