Leetcode进阶之路——Weekly Contest 128

1012. Complement of Base 10 Integer

Every non-negative integer N has a binary representation. For example, 5 can be represented as “101” in binary, 11 as “1011” in binary, and so on. Note that except for N = 0, there are no leading zeroes in any binary representation.
The complement of a binary representation is the number in binary you get when changing every 1 to a 0 and 0 to a 1. For example, the complement of “101” in binary is “010” in binary.
For a given number N in base-10, return the complement of it’s binary representation as a base-10 integer
Example 1:
Input: 5
Output: 2
Explanation: 5 is “101” in binary, with complement “010” in binary, which is 2 in base-10.
Example 2:
Input: 7
Output: 0
Explanation: 7 is “111” in binary, with complement “000” in binary, which is 0 in base-10.
Example 3:
Input: 10
Output: 5
Explanation: 10 is “1010” in binary, with complement “0101” in binary, which is 5 in base-10.

输入一个整数,输出其反码的十进制
easy难度的题,用一个数保存第几位,一个数保存每次对2取余并取反后的数,累加即可:

class Solution {
public:
    int bitwiseComplement(int N) {
        # 注意当N=0时,直接返回1
        if(N == 0) return 1;
        int res = 0;
        string s = "";
        while(N)
        {
            int m = N % 2;
            m = !m;
            s = char(m + 48) + s;
            N /= 2;
        }
        for(int i = 0; i < s.length(); ++i)
        {
            res = res * 2 + s[i] - 48;
        }
        return res;
    }
};

1013. Pairs of Songs With Total Durations Divisible by 60

In a list of songs, the i-th song has a duration of time[i] seconds.
Return the number of pairs of songs for which their total duration in seconds is divisible by 60. Formally, we want the number of indices i < j with (time[i] + time[j]) % 60 == 0.
Example 1:
Input: [30,20,150,100,40]
Output: 3
Explanation: Three pairs have a total duration divisible by 60:
(time[0] = 30, time[2] = 150): total duration 180
(time[1] = 20, time[3] = 100): total duration 120
(time[1] = 20, time[4] = 40): total duration 60
Example 2:
Input: [60,60,60]
Output: 3
Explanation: All three pairs have a total duration of 120, which is divisible by 60.

输入一串数组,计算相加能被60整除的所有整数对
用一个哈希表保存数组中每个数对60取余的数,然后跟与其对应的余数相乘即可

class Solution {
public:
    int numPairsDivisibleBy60(vector<int>& time) {
		map<int, int> m;
		for (int t : time)
		{
			m[t % 60] ++;
		}
		int res = 0;
		map<int, int>::iterator it = m.begin();
		while (it != m.end())
		{
			double a = it->first, b = 60 - a;
			# 遍历到a = 30即可,后面的都是被计算过的
			if (a > 30) break;
			if (b == a || b == 60)
			{
				int cnt = it->second - 1;
				res += (cnt + 1) * cnt / 2;
			}
			else res += (m[b] * it->second);
			it++;
		}
		return res;
	}
};

或者直接从头到尾遍历一遍,因为对前面的余数,其对应的余数个数在最开始都是0,也就不存在重复计算的问题

class Solution {
public:
    int numPairsDivisibleBy60(vector<int>& time) {
		int res = 0;
        map<int, int> m;
        for(int t: time)
        {
            t %= 60;
            res += m[(60-t)%60];
            m[t]++;
        }
		return res;
	}
};

1014. Capacity To Ship Packages Within D Days

A conveyor belt has packages that must be shipped from one port to another within D days.
The i-th package on the conveyor belt has a weight of weights[i]. Each day, we load the ship with packages on the conveyor belt (in the order given by weights). We may not load more weight than the maximum weight capacity of the ship.
Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D days.
Example 1:
Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
Output: 15
Explanation:
A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10
Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.
Example 2
Input: weights = [3,2,2,4,1,4], D = 3
Output: 6
Explanation:
A ship capacity of 6 is the minimum to ship all the packages in 3 days like this:
1st day: 3, 2
2nd day: 2, 4
3rd day: 1, 4
Example 3:
Input: weights = [1,2,3,1,1], D = 4
Output: 3
Explanation:
1st day: 1
2nd day: 2
3rd day: 3
4th day: 1, 1

给定一个重量数组和一个时间,天数D,求出最小的载重量,使得在D天内,所有物品都能被运送完
要注意的一点是,所有物品必须按序运送,不能说最大的物品和最小的物品一起运送
典型的二分查找,假设初始的最小值为总重量/D,最大值为总重量,则每次判断平均值是否能满足被运送完,并保存,最后返回最小的重量

class Solution {
public:
    int shipWithinDays(vector<int>& weights, int D) {
		int len = weights.size();
		set<int> m;
		int fir = 0, snd = 0;
        int cnt = 1;
		for (int i = len - 1; i >= 0; --i)
		{
			fir += weights[i];
		}
		snd = fir;
		fir = int(fir * 1.0 / D + 0.9999);
		while (fir <= snd)
		{
			int mid = (fir + snd) / 2;
			if (canShip(weights, D, mid))
			{
				snd = mid - 1;
				m.insert(mid);
			}
			else
			{
				fir = mid + 1;
			}
		}
		set<int>::iterator it = m.begin();
		return *it;
	}

	bool canShip(vector<int> &weights, int d, int st)
	{
		int cnt = 0, pos = 0;
		while (d--)
		{
			int cur = st;
			for (int i = pos; i < weights.size(); ++i)
			{
				if (cur >= weights[i])
				{
					cur -= weights[i];
					cnt++;
				}
				else
				{
					pos = i;
					break;
				}
			}
			if (cnt == weights.size()) return true;
		}
		return false;
	}
};

1015. Numbers With Repeated Digits

Given a positive integer N, return the number of positive integers less than or equal to N that have at least 1 repeated digit.
Example 1:
Input: 20
Output: 1
Explanation: The only positive number (<= 20) with at least 1 repeated digit is 11.
Example 2:
Input: 100
Output: 10
Explanation: The positive numbers (<= 100) with atleast 1 repeated digit are 11, 22, 33, 44, 55, 66, 77, 88, 99, and 100.
Example 3:
Input: 1000
Output: 262

给定一个整数N,找出所有≤N的数中,包含重复数字的整数的个数
这道题直接做可能不太方便,逆向思维,先找出不包含重复数字的整数个数,如K个,则N-K即为包含重复数字的个数
整体的思路,假设N=23456
先找所有1、2、3、4位数不包含重复数字:
一位数:9个
二位数:20、21、23 ~ 29;30、31、32 ~ 39 · · ·可以发现总共有9 * 9 = 81个
同理,三位数、四位数分别有:9 * 9 * 8 和 9 * 9 * 8 * 7个不包含重复数字的整数
那么对于五位数,先考虑1xxxx,共有9 * 8 * 7 * 6 个
再考虑20xxx和21xxx(22xxx已经包含重复数字,因此无需计算),该情况共有8 * 7 * 6个
再考虑230xx、231xx(232xx、233xx已包含重复数字),该情况有7 * 6个
以此类推,重新整理逻辑后,则可得到如下AC代码:

class Solution {
public:
    int numDupDigitsAtMostN(int N) {
		if (N < 11) return 0;
		string s = to_string(N + 1);
		int len = s.length();
		int res = 0;
		for (int i = 0; i < len - 1; ++i)
		{
			res += A(9, i) * 9;
		}
		string str = "";
		for (int i = 0; i < len; ++i)
		{			
			int n = s[i] - '0';
			if (i == 0) n--;
			//else n++;
			int cnt = n;
			for (int j = 0; j < str.size(); ++j)
			{
				if (str[j] - '0' < n) cnt--;
			}
			res += cnt * A(9 - str.size(), len - i - 1);
			// 若当前已存在重复数字,直接跳出循环
			if (str.find(s[i]) != string::npos)
				break;
			str += s[i];
		}
		return N - res;
	}

	int A(int m, int n)
	{
		return n == 0 ? 1 : A(m, n - 1) * (m - n + 1);
	}
};

为简便,先对原数字N做+1运算,函数A为排列组合,计算123*…*m

上一篇:一、最小绝对差(Weekly Contest 155)


下一篇:前端周刊,给前端同学准备的每周1小时阅读清单