Leetcode每天五题-08

  1. 相交链表

编写一个程序,找到两个单链表相交的起始节点。

思路:

求出每个链表的长度,长的那个先走几步,然后一起走,遇到相等就停步

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        node = headA
        len_a = 0
        len_b = 0
        while node:
            node = node.next
            len_a +=1
        node = headB
        while node:
            node = node.next
            len_b +=1
        gap = abs(len_a-len_b)
        if len_a > len_b:
            while gap !=0:
                headA = headA.next
                gap-=1
        if len_b > len_a:
            while gap !=0:
                headB = headB.next
                gap-=1
        while headA != headB:
            headA = headA.next
            headB = headB.next
        return headA

简化版:

调试了好久,还是要想清楚阿…

class Solution(object):
    @classmethod
    def getIntersectionNode(self, headA, headB):
        if(headA == None or headB == None):
            return None
        nodeA = headA
        nodeB = headB
        len_a, len_b = 0, 0
        while nodeA != None or nodeB != None:
            nodeA = nodeA if nodeA == None else nodeA.next
            nodeB = nodeB if nodeB == None else nodeB.next
            len_a = len_a + 1 if nodeA != None else len_a
            len_b = len_b + 1 if nodeB != None else len_b
        gap = abs(len_a-len_b)
        while gap > 0:
            headA = headA if len_a < len_b else headA.next
            headB = headB if len_a > len_b else headB.next
            gap -= 1
        while headA != headB:
            headA = headA.next
            headB = headB.next
        return headA

讨论区:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        /**
        定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差)
        两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度
        **/
        if(headA == null || headB == null) return null;
        ListNode pA = headA, pB = headB;
        // 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null
        while(pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }
}
  1. 求众数

给定一个大小为n的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

class Solution(object):
    def majorityElement(self, nums):
        #摩尔投票算法 不是很懂
        ans = nums[0]
        count = 0
        for num in nums[1:]:
            if num == ans:
                count +=1
            elif count > 0:
                count -=1
            else:
                ans = num
        return ans
  1. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:

输入: [1,2,3,1]
输出: 4

解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入: [2,7,9,3,1]
输出: 12

解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

备注:

递归必须使用记忆化搜索,不然会超时

class Solution(object):
    map = []
    def rob(self, nums):
        self.map = [-1 for x in range(len(nums))]
        return self.robCore(nums,0)
    def robCore(self,nums,k):
        if k>=len(nums):
            return 0
        if self.map[k] != -1:
            return self.map[k]
        #当只剩两个元素时,可以直接求解
        n = len(nums[k:])
        if n<=2:
            return max(nums[k:])
        a = max(self.robCore(nums,k+2),self.robCore(nums,k+1))
        b = self.robCore(nums,k+2)+nums[k]
        self.map[k] = max(a,b)
        return self.map[k]

讨论区动态规划解法:

public int rob2(int[] nums) {
    int n = nums.length;
    if (n == 0) {
        return 0;
    }
    // memo[i] 表示考虑抢劫 nums[i...n-1] 所能获得最大收益(不是说一定从 i 开始抢劫)
    int[] memo = new int[n];
    // 先考虑最简单的情况
    memo[n - 1] = nums[n - 1];
    for (int i = n - 2; i >= 0; i--) {
        // memo[i] 的取值在考虑抢劫 i 号房子和不考虑抢劫之间取最大值
        memo[i] = Math.max(nums[i] + (i + 2 >= n ? 0 : memo[i + 2]), nums[i + 1] + (i + 3 >= n ? 0 : memo[i + 3]));
    }
    return memo[0];
}

public int rob3(int[] nums) {
    int n = nums.length;
    if (n <= 1) return n == 0 ? 0 : nums[0];
    int[] memo = new int[n];
    memo[0] = nums[0];
    memo[1] = Math.max(nums[0], nums[1]);
    for (int i = 2; i < n; i++)
        memo[i] = Math.max(memo[i - 1], nums[i] + memo[i - 2]);
    return memo[n - 1];
}
  1. 岛屿的个数

给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。

示例 1:

输入:

11110
11010
11000
00000

输出: 1

示例 2:

输入:
11000
11000
00100
00011

输出: 3
思路:

遇到1时将所有可达的为1的点合并

class Solution(object):
    dx = [1,0,-1,0]
    dy = [0,-1,0,1]
    def numIslands(self, grid):
        ans = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    self.dfs(grid,i,j)
                    ans +=1
        return ans
    def dfs(self,grid,i,j):
        grid[i][j] = '.'
        for k in range(4):
            m = i+self.dx[k]
            n = j+self.dy[k]
            if m>-1 and m<len(grid) and n >-1 and n<len(grid[0]) and grid[m][n] == '1':
                self.dfs(grid,m,n)
        return
  1. 反转链表

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:

你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

迭代式:

class Solution(object):
    def reverseList(self, head):
        pre,cur = None,head
        while cur != None:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        return pre

递归:

class Solution(object):
    def reverseList(self, head):
        if not head or not head.next:
            return head
        new_head = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return new_head

讨论区:

class Solution(object):
    def reverseList(self, head):
        pre,cur = None,head
        while cur:
            pre,pre.next,cur = cur, pre, cur.next
        return pre
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值