LeetCode刷题笔记(Java)---第261-280题

前言

需要开通vip的题目暂时跳过

笔记导航

点击链接可跳转到所有刷题笔记的导航链接

263. 丑数

编写一个程序判断给定的数是否为丑数。

丑数就是只包含质因数 2, 3, 5 的正整数。

在这里插入图片描述

  • 解答

    		public boolean isUgly(int num) {
            if(num <= 0)return false;
            if(num == 1)return true;
            if(num % 5 == 0)return isUgly(num/5);
            if(num % 3 == 0)return isUgly(num/3);
            if(num % 2 == 0)return isUgly(num/2);
            return false;
        }
    
  • 分析

    1. 递归出口,小于等于0的直接返回false
    2. 等于1的时候返回true;
    3. 依次将num除以5、3、2 看哪个可以整除,就执行递归
    4. 若无法整除5、3、2,说明存在其他质数
  • 提交结果

在这里插入图片描述

264.丑数 II

编写一个程序,找出第 n 个丑数。

丑数就是质因数只包含 2, 3, 5正整数

在这里插入图片描述

  • 解答
		//方法一
		public int nthUglyNumber(int n) {
	        long[] ugly = new long[1690];
	        PriorityQueue<Long> queue = new PriorityQueue<>();
	        HashSet<Long> set = new HashSet<>();
	        queue.add(1L);
	        set.add(1L);
	        int[] numbers = {2,3,5};
	        for(int i = 0;i < 1690;i++){
	            long current = queue.poll();
	            ugly[i] = current;
	            for(int number : numbers){
	                if(!set.contains(current * number)){
	                    set.add(current*number);
	                    queue.add(current*number);
	                }
	            }
	        }
	        return (int)ugly[n-1];
        }
		//方法二
		class Ugly {
	        public int[] nums = new int[1690];
	        Ugly() {
	            HashSet<Long> seen = new HashSet();
	            PriorityQueue<Long> heap = new PriorityQueue<Long>();
	            seen.add(1L);
	            heap.add(1L);
	
	            long currUgly, newUgly;
	            int[] primes = new int[]{2, 3, 5};
	            for(int i = 0; i < 1690; ++i) {
	                currUgly = heap.poll();
	                nums[i] = (int)currUgly;
	                for(int j : primes) {
	                    newUgly = currUgly * j;
	                    if (!seen.contains(newUgly)) {
	                        seen.add(newUgly);
	                        heap.add(newUgly);
	                    }
	                }
	            }
	        }
	    }
	    class Solution {
	        public static Ugly u = new Ugly();
	        public int nthUglyNumber(int n) {
	            return u.nums[n - 1];
	        }
	    }
		//方法三
		class Ugly{
        	int[] numbers = new int[1690];
	        Ugly(){
	            numbers[0] = 1;
	            int i2 = 0,i3 = 0,i5 = 0;
	            int ugly = 1;
	            for(int i = 1;i<1690;i++){
	                ugly = Math.min(Math.min(numbers[i2] * 2,numbers[i3] * 3),numbers[i5]*5);
	                numbers[i] = ugly;
	                if(ugly == numbers[i2]*2) ++i2;
	                if(ugly == numbers[i3]*3) ++i3;
	                if(ugly == numbers[i5]*5) ++i5;
	            }
	        }
  		}
	    class Solution {
	        public int nthUglyNumber(int n) {
	            Ugly ugly = new Ugly();
	            return ugly.numbers[n-1];
	        }
	    }

  • 分析

    1. 预计算 1690 个丑数:
      初始化预计算用到的数组 nums,堆 queue 和哈希表 set 跟踪在堆中出现过的元素,避免重复。
    2. 循环计算丑数,每个步骤:
      弹出堆中最小的数字 k 并添加到数组 nums 中。
      若 2k,3k,5k 不存在在哈希表中,则将其添加到栈中并更新哈希表。
      返回在数组中预先计算好的丑数。
    3. 方法二 则是将预计算的操作只进行一次,存在一个静态变量里。
    4. 方法三使用动态规划,利用三个指针,分别来得到当前的最小丑数。并移动指针。
  • 提交结果

    方法一
    在这里插入图片描述

    方法二
    在这里插入图片描述
    方法三
    在这里插入图片描述

268.缺失数字

给定一个包含 0, 1, 2, ..., nn 个数的序列,找出 0 … n 中没有出现在序列中的那个数。

在这里插入图片描述

  • 解答

    		//方法一
    		public int missingNumber(int[] nums) {
                Arrays.sort(nums);
                int len = nums.length;
                for(int i = 0;i<len;i++){
                    if(i != nums[i])return i;
                }
                return len;
            }
    		// 方法二
    		public int missingNumber(int[] nums) {
                int len = nums.length;
                int numbers[] = new int[len + 1];
                for(int i = 0;i<len;i++){
                    numbers[nums[i]] = 1;
                }
                for(int i = 0;i < len + 1;i++){
                    if(numbers[i] == 0)return i;
                }
                return -1;
            }
    		//方法三
    		public int missingNumber(int[] nums) {
                int len = nums.length;
                int res = len;
                for(int i = 0;i<len;i++){
                    res = res^i^nums[i];
                }
                return res;
            }
    
  • 分析

    1. 方法一 先排序,然后遍历寻找不连续的点,即没有出现的值。
    2. 方法二空间换时间,用一个数组来记录出现过的数字,对应位置设为1,然后在遍历这个数组,找出没有出现过的数字。方法二的数组可以用哈希表替代。
    3. 方法三用异或来实现,两个相同的数字异或结果为0.假设nums的大小为10,那么将0-10和数组中的所有数字进行异或,就可以找出数组中没有出现过的数字。因为若数组中有这个数字,则表明出现过两次,则结果为0.所以最后异或的结果就是没有出现在数组中的数字,
  • 提交结果

    方法一

在这里插入图片描述

方法二

在这里插入图片描述

方法三

在这里插入图片描述

273. 整数转换英文表示

将非负整数转换为其对应的英文表示。可以保证给定输入小于 231 - 1 。

在这里插入图片描述

  • 解答
public String one(int num) {
  	switch(num) {
        case 1: return "One";
        case 2: return "Two";
        case 3: return "Three";
        case 4: return "Four";
        case 5: return "Five";
        case 6: return "Six";
        case 7: return "Seven";
        case 8: return "Eight";
        case 9: return "Nine";
    }
    return "";
}
public String twoLessThan20(int num) {
    switch(num) {
        case 10: return "Ten";
        case 11: return "Eleven";
        case 12: return "Twelve";
        case 13: return "Thirteen";
        case 14: return "Fourteen";
        case 15: return "Fifteen";
        case 16: return "Sixteen";
        case 17: return "Seventeen";
        case 18: return "Eighteen";
        case 19: return "Nineteen";
    }
    return "";
}
public String ten(int num) {
    switch(num) {
        case 2: return "Twenty";
        case 3: return "Thirty";
        case 4: return "Forty";
        case 5: return "Fifty";
        case 6: return "Sixty";
        case 7: return "Seventy";
        case 8: return "Eighty";
        case 9: return "Ninety";
    }
    return "";
}

public String two(int num) {
    if (num == 0)
        return "";
    else if (num < 10)
        return one(num);
    else if (num < 20)
        return twoLessThan20(num);
    else {
        int tenner = num / 10;
        int rest = num - tenner * 10;//个位数
        if (rest != 0)
          return ten(tenner) + " " + one(rest);
        else
          return ten(tenner);
    }
}
public String three(int num) {
    int hundred = num / 100;//百位数
    int rest = num - hundred * 100;//个位十位
    String res = "";
    if (hundred * rest != 0)
        res = one(hundred) + " Hundred " + two(rest);
    else if ((hundred == 0) && (rest != 0))
        res = two(rest);
    else if ((hundred != 0) && (rest == 0))
        res = one(hundred) + " Hundred";
    return res;
}

public String numberToWords(int num) {
    if (num == 0)
        return "Zero";

    int billion = num / 1000000000;
    int million = (num - billion * 1000000000) / 1000000;
    int thousand = (num - billion * 1000000000 - million * 1000000) / 1000;
    int rest = num - billion * 1000000000 - million * 1000000 - thousand * 1000;
    String result = "";
    if (billion != 0)
        result = three(billion) + " Billion";
    if (million != 0) {
        if (! result.isEmpty())
            result += " ";
        result += three(million) + " Million";
    }
    if (thousand != 0) {
        if (! result.isEmpty())
            result += " ";
        result += three(thousand) + " Thousand";
    }
    if (rest != 0) {
        if (! result.isEmpty())
            result += " ";
        result += three(rest);
    }
    return result;
}
  • 分析

    1. 分治的思想,将数字拆成3个一组,
    2. 三个一组中又分成首位和后两位
    3. 首位就是1-9+Hundred
    4. 后两位分成0-9 10-19 20-99
    5. 将数字拆成三个一组,得到每一组的表达,根据所在的位置在每一组的表达之后加上单位即可
  • 提交结果

    在这里插入图片描述

274. H 指数

给定一位研究者论文被引用次数的数组(被引用次数是非负整数)。编写一个方法,计算出研究者的 h 指数。

h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (N 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。(其余的 N - h 篇论文每篇被引用次数 不超过 h 次。)

例如:某人的 h 指数是 20,这表示他已发表的论文中,每篇被引用了至少 20 次的论文总共有 20 篇。

在这里插入图片描述

  • 解答
public int hIndex(int[] citations) {
    Arrays.sort(citations);
    int len = citations.length;
    for(int i = 0;i < len;i++){
        int number = Math.min(citations[i],len-i);
    if(number == len-i)
        return number;
    }
    return 0;
}
  • 分析

    1. 将数组先排序
    2. 然后遍历数组,计算当前值与len-i中的较小者。例如0,1,7,8,9。遍历到第三位的时候是7,len-i是3,得到的结果就是3。
    3. 若b中得到的结果等于len-i 则就是要找的H指数
  • 提交结果
    在这里插入图片描述

275. H指数 II

给定一位研究者论文被引用次数的数组(被引用次数是非负整数),数组已经按照升序排列。编写一个方法,计算出研究者的 h 指数。

h 指数的定义: “h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (N 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。(其余的 N - h 篇论文每篇被引用次数不多于 h 次。)"

在这里插入图片描述

  • 解答
public int hIndex(int[] citations) {
    int len = citations.length;
    if(len == 0) return 0;
    int left = 0;
    int right = len-1;
    while(left <= right){
        int mid = (left+right)/2;
        if(citations[mid] == len - mid)return len - mid;
        if(citations[mid] < len - mid)left = mid + 1;
        else right = mid - 1;
    }
    return len - left;
}
  • 分析

    1. 二分查找来实现,可以减少搜索的时间复杂度
    2. mid所指向的值等于len-mid则是要找的H指数直接返回
    3. 否则当mid所指向的值小于len-mid,那么H指数必定在mid的右侧,所以left = mid+1
    4. 同理当mid所指向的值大于len-mid时,那么H指数必定在mid的左侧,所以right = mid-1
  • 提交结果

在这里插入图片描述

278. 第一个错误的版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

在这里插入图片描述

  • 解答
public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1;
        int right = n;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(isBadVersion(mid))right = mid-1;
            else left = mid + 1;
        }
        return left;
    }
}
  • 分析

    1. 二分查找来实现

    2. 关键在于mid的计算,left + (right-left)/2;若使用(left+right)/2,会导致left+right计算的时候溢出,得到错误的mid结果。

  • 提交结果
    在这里插入图片描述

279. 完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

在这里插入图片描述

  • 解答
public int numSquares(int n) {
    if(n<=3)return n;
    int[] dp = new int[n + 1];
    for (int i = 0; i < n + 1; i++) {
        dp[i] = Integer.MAX_VALUE;
    }
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 3;
    int[] sqares = new int[(int) Math.sqrt(n)];
    for (int i = 0; i < sqares.length; i++) {
        sqares[i] = (int) Math.pow(i + 1, 2);
    }
    for (int i = 4; i <= n; i++) {
        for (int j = 0; j < sqares.length; j++) {
            if (i - sqares[j] >= 0)
                 dp[i] = Math.min(dp[i - sqares[j]] + 1, dp[i]);
        }
    }
    return dp[n];
}
//方法二
Set<Integer> square_nums = new HashSet<Integer>();

protected boolean is_divided_by(int n, int count) {
    if (count == 1) {
        return square_nums.contains(n);
    }

    for (Integer square : square_nums) {
        if (is_divided_by(n - square, count - 1)) {
            return true;
        }
    }
    return false;
}

public int numSquares(int n) {
    square_nums.clear();

    for (int i = 1; i * i <= n; ++i) {
        square_nums.add(i * i);
    }
    int count = 1;
    for (; count <= n; ++count) {
        if (is_divided_by(n, count))
              return count;
    }
    return count;
}
//方法三
public int numSquares(int n) {
    Set<Integer> squares = new HashSet<>();
    for(int i = 1; i*i <= n;i++){
		    squares.add(i*i);
		}
    Set<Integer> queue = new HashSet<>();
    queue.add(n);
    int res = 0;
    while(!queue.isEmpty()){
        res++;
        Set<Integer> nextQueue = new HashSet<>();
        for(Integer remain:queue){
            for(Integer square:squares){
                if(remain - square == 0)return res;
                if(remain -square < 0)continue;
                nextQueue.add(remain - square);
            }
        }
        queue = nextQueue;
    }
    return res;
}
  • 分析

    1. 方法一使用动态规划实现,记录当前位置组成的完全平方数的最少个数。
    2. 寻找最少个数,就是当前位置的值,减去比他小的完全平方数的dp对应的数字+1.选择最小的一个作为这一位的结果。
    3. 最后返回dp数组最后一位即是答案。
    4. 方法二使用递归实现
    5. 次数从1开始遍历,在规定次数内能否由完全平方数组合而成。
    6. 方法三,当作树来处理,根结点是n,其孩子就是n减去比它小的完全平方数。再继续判断孩子的孩子,当某一个孩子是完全平方数的时候,这时候就找到了最少个数组合的结果。返回层数即可。
  • 提交结果

    方法一
    在这里插入图片描述

    方法二
    在这里插入图片描述

    方法三
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/gongsenlin341/article/details/107628011