From 4be8f9021acf82dc751d924c5da4eaa512261ce0 Mon Sep 17 00:00:00 2001 From: "xuemin.zhu" Date: Sun, 30 Jun 2019 20:12:03 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E5=9B=9B=E5=91=A8=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A#35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Week_04/id_35/Leetcode_169_35.java | 107 +++++++++++++++++++++++++++++ Week_04/id_35/Leetcode_198_35.java | 58 ++++++++++++++++ Week_04/id_35/Leetcode_213_35.java | 68 ++++++++++++++++++ Week_04/id_35/Leetcode_70_35.java | 51 ++++++++++++++ 4 files changed, 284 insertions(+) create mode 100644 Week_04/id_35/Leetcode_169_35.java create mode 100644 Week_04/id_35/Leetcode_198_35.java create mode 100644 Week_04/id_35/Leetcode_213_35.java create mode 100644 Week_04/id_35/Leetcode_70_35.java diff --git a/Week_04/id_35/Leetcode_169_35.java b/Week_04/id_35/Leetcode_169_35.java new file mode 100644 index 00000000..e443734c --- /dev/null +++ b/Week_04/id_35/Leetcode_169_35.java @@ -0,0 +1,107 @@ +package com.leecode.week04; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +/** + * 求众数 给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 + * + * 你可以假设数组是非空的,并且给定的数组总是存在众数。 + * + * @author xuemin.zhu + */ +public class Leetcode_169_35 { + + public static void main(String[] args) { + + Leetcode_169_35 lc = new Leetcode_169_35(); + //System.out.println(lc.majorityElement(new int[]{3, 2, 3})); + System.out.println(lc.majorityElement(new int[]{2, 2, 1, 1, 1, 2, 2})); + System.out.println(lc.majorityElement(new int[]{1})); + System.out.println(lc.majorityElement(new int[]{2,2})); + System.out.println(lc.majorityElement(new int[]{6,5,5})); + + } + + /** + * Boyer-Moore: + * 思路说明:把所有数据都看成是众数和非众数两类,然后就像玩消消乐那样一个碰一个去抵消掉 这里是不一样的抵消掉 + * 因为众数是数量比较多的,把全部非众数灭掉之后还有剩,剩下的就是我们要找的众数了 + */ + public int majorityElement(int[] nums) { + + //题目中保证要有众数,两个元素的情况只能是两个一样的了 + if (nums.length == 1 || nums.length == 2) { + return nums[0]; + } + + int majorIndex = 0;//首先选择0作为众数 + int majorCount = 0;//当前众数的计数个数 + for (int i = 0; i < nums.length; i++) { + if (nums[i] == nums[majorIndex]) { + majorCount++; + } else { + majorCount--; + } + + if (majorCount == 0) { + //当前众数是0之后需要重新选举新的众数,i 会在经过majorCount时majorCount会变成1 + majorIndex = i + 1; + + } + } + + return nums[majorIndex]; + } + + + /** + * 思路1:最直接的搞法就是先计算出每个数字出现的次数,再看看是不是超过n/2 这里想试试jdk8中新式写法^^ + */ + + public int majorityElement_v1(int[] nums) { + + Map map = Arrays.stream(nums) + .mapToObj(num -> new Tuple(String.valueOf(num), num)) + .collect(Collectors.groupingBy(Tuple::getKey, Collectors.counting())); + + List> entrys = map.entrySet().stream() + .filter(s -> s.getValue() > nums.length / 2).collect(Collectors.toList()); + + if (entrys.isEmpty() || entrys.size() != 1) { + return -1; + } + + return Integer.valueOf(entrys.get(0).getKey()); + } + + static class Tuple { + + private String key; + private Integer val; + + public Tuple(String key, Integer val) { + this.key = key; + this.val = val; + } + + public Integer getVal() { + return val; + } + + public void setVal(Integer val) { + this.val = val; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + } +} diff --git a/Week_04/id_35/Leetcode_198_35.java b/Week_04/id_35/Leetcode_198_35.java new file mode 100644 index 00000000..4bf7a11d --- /dev/null +++ b/Week_04/id_35/Leetcode_198_35.java @@ -0,0 +1,58 @@ +package com.leecode.week04; + +/** + * 打家劫舍 + * 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 + * + * 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 + * + */ +public class Leetcode_198_35 { + + public static void main(String[] args) { + Leetcode_198_35 lc=new Leetcode_198_35(); + + System.out.println(lc.rob(new int[]{1,2,3,1})); + + System.out.println(lc.rob(new int[]{2,9,7,3,1})); + + + } + + /** + * 相邻的房间不能偷,转换成我在当前的一套房间的行为 + * 1.前一个房间我没有偷,那么当前的房间我可以偷 + * 2.前一个房间我是偷了的,当前的房间就不能偷了 + * 所以偷到当前的房间的最高金额就是在两种方案中选择最高的 + * + * dp[i]=max(dp[i-1]+0),dp[i-2]+num[i] + * + * @param nums + * @return + */ + public int rob(int[] nums) { + int[] dp=new int[nums.length]; + + if(nums==null||nums.length==0){ + return 0; + } + + if(nums.length==1){ + return nums[0]; + } + + if(nums.length==2){ + return Math.max(nums[0],nums[1]); + } + + + dp[0]=nums[0]; + dp[1]=Math.max(dp[0],nums[1]);//第一次偷了就是dp[0],第一次不偷0+第二次偷num[1],两种情况找个比较大的 + + for(int i=2;i=3的时候都有这种关系 dp[n]=dp[n-1]+d[n-2],表示的是剩下一步走到N的情况和剩下走两步走到N的情况,所以要走到N步就是前面两者的和 + */ + public int climbStairs(int n) { + int oneStep = 1; + int twoStep = 2; + + switch (n) { + case 1: + return oneStep; + case 2: + return twoStep; + default: + int[] dp = new int[n]; + dp[0] = oneStep; + dp[1] = twoStep; + for (int i = 2; i < n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n - 1]; + } + + + } +}