leetcode刷题记录(949、367、374)

版权声明:尊重别人的劳动成果 https://blog.csdn.net/adminhyh/article/details/85246233

2018.12.25 leetcode 刷题总结

题号:949

给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间。
最小的 24 小时制时间是 00:00,而最大的是 23:59。从 00:00 (午夜)开始算起,过得越久,时间越大。
以长度为 5 的字符串返回答案。如果不能确定有效时间,则返回空字符串。

示例 1:
输入:[1,2,3,4]
输出:“23:41”
示例 2:
输入:[5,5,5,5]
输出:""
提示:
A.length == 4
0 <= A[i] <= 9

我的想法:

  1. 获得所有合法的小时组合,并记录它们在数组中的位置
  2. 遍历所有合法的小时数,获得相应小时数最大合法的分钟数,即数组中去除组合成小时数的两个数去组成最大的合法的分钟数
  3. 在遍历的时候找出最大合法的小时数+分钟数的组合
  4. 所有数字的不满足的结果或初始值都会被赋成 -1

对应程序:

// java
class Solution {
	public String largestTimeFromDigits(int[] A) {
		// 获得所有合法的小时组合
		// hourMap<小时数,List<组成小时数的两个数字的下标>>
		Map<Integer, List<Integer>> hourMap = hourCombo(A);
		// 若不存在,返回空
		if(hourMap.size() == 0) {
			return "";
		}
		// 记录最大的小时数
		int maxHour = -1;
		// 记录同小时数相对应的分钟数
		int maxMin = -1;
		// 遍历所有合法的小时数
		for(Integer hour : hourMap.keySet()) {
			List<Integer> list = hourMap.get(hour);
			// 获得与小时数相对应的分钟数
			int minute = maxMinute(A, list);
			// 若无合法的分钟数,跳到下一个小时数
			if(minute == -1) {
				continue;
			}else {
				// 找出最大的组合
				// 注意,能进到这个else中说明小时+分钟的组合都是合法的,
				// 因此,找出小时数最大的就是组合后时间最大的
				if(hour > maxHour) {
					maxHour = hour;
					maxMin = minute;
				}
			}
		}
		// 若不存在,返回空
		if(maxHour == -1 || maxMin == -1) {
			return "";
		}
		// 转换格式,将一位数的数字前面加0
		String hourStr = String.valueOf(maxHour);
		if(maxHour < 10) {
			hourStr = "0" + hourStr;
		}
		
		String minuteStr = String.valueOf(maxMin);
		if(maxMin < 10) {
			minuteStr = "0" + minuteStr; 
		}
		// 返回 小时:分钟
		return hourStr + ":" + minuteStr;
	}
	// 获得最大的合法的分钟数
	// @param A:所给数组
	// @param list:组成小时数的两个数的下标
	private int maxMinute(int[] A, List<Integer> list) {
		boolean flag = true;
		int a = -1;
		int b = -1;
		// 拿到数组中其余两个数,分别赋给a,b
		for(int i = 0 ;i < A.length; ++i) {
			if(i == list.get(0) || i == list.get(1)) {
				continue;
			}
			if(flag) {
				a = A[i];
				flag = false;
			}else {
				b = A[i];
			}
		}
		// 得到所有的分钟数(2种)
		int ab = a * 10 + b;
		int ba = b * 10 + a;
		// 找出在[0,59]中最大的一个数并返回,不存在返回-1
		int result = -1;
		if(ab >= 0 && ab <= 59) {
			if(ab > result) {
				result = ab;
			}
		}
		
		if(ba >= 0 && ba <= 59) {
			if(ba > result) {
				result = ba;
			}
		}
		
		return result;
		
	}
	// 获得所有合法的小时数的组合,并记录他们的下标位置
	private Map<Integer, List<Integer>> hourCombo(int[] A) {
		Map<Integer, List<Integer>> map = new HashMap<>();
		List<Integer> list = null;
		for(int i = 0; i < A.length; ++i) {
			for(int j = 0; j < A.length; ++j) {
				// 不能和自己做小时数
				if(j == i) {
					continue;
				}
				// 计算所有可能的小时数
				int num = A[i] * 10 + A[j];
				// 将小时数限制在[0,23]之间
				if(num >= 0 && num <= 23) {
					list = new ArrayList<>();
					// 记录下标
					list.add(i);
					list.add(j);
					// 添加结果
					map.put(num, list);
				}
			}
		}
		
		return map;
	}
}

题号:367

给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
说明:不要使用任何内置的库函数,如 sqrt。

示例 1:
输入:16
输出:True
示例 2:
输入:14
输出:False

我的想法:

n的完全平方等于n项由1开始的奇数的和
e.g. 16 = 1 + 3 + 5 + 7

对应程序:

// java
class Solution {
    public boolean isPerfectSquare(int num) {
			int flag = 1;
	        while(num > 0) {
	        	num -= flag;
	        	flag += 2;
	        	
	        	if(num == 0) {
	        		return true;
	        	}
	        }
	        
			return false;
    }
}

这个办法在所给数字非常大的时候会费时,提交记录中执行用时0ms的解答中用的是一种缩小区间逐渐逼近答案的办法,类似二分查找法

程序:

// java
class Solution {
    public boolean isPerfectSquare(int num) {
        long temp=num/2+1;
        long start=0;
        long end=temp;
        while(start<=end){
            long mid=start+(end-start)/2;
            long result=mid*mid;
            if(result==num)
                return true;
            else if(result<num)
                start=mid+1;
            else
                end=mid-1;
        }
        return false;
    }
}

上面的程序中,初始区间选在[0,n/2+1]之间,可以保证任何数的平方根都落在此区间,因为 (n/2+1)2 - n = n2/4 + 1 一定是大于零的。

题号:374

我们正在玩一个猜数字游戏。 游戏规则如下:
我从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。
每次你猜错了,我会告诉你这个数字是大了还是小了。
你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0):
-1 : 我的数字比较小
1 : 我的数字比较大
0 : 恭喜!你猜对了

示例 :
输入: n = 10, pick = 6
输出: 6

我的想法:

二分查找,缩小查找区间,递归调用guess()函数

对应程序:

// java
/* The guess API is defined in the parent class GuessGame.
   @param num, your guess
   @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
      int guess(int num); */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        return guessNumber(1, n);
    }
    // @param start:区间左端点
    // @param end: 区间右端点
    private int guessNumber(int start, int end) {
    	// 二分查找,标志位数字
    	// 不要直接写成(start + end)/ 2,防止溢出
		int temp = start + (end - start)/2;
		// 得到查询结果标志
		int guessFlag = guess(temp);
		
		if(guessFlag == 0) {
			// 递归出口
			return temp;
		}else if(guessFlag < 0) {
			// 区间向左缩小
			return guessNumber(start, temp-1);
		}else {
			// 区间向右缩小
			return guessNumber(temp+1, end);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/adminhyh/article/details/85246233