1. 程式人生 > 其它 >leetCode330:按要求補齊陣列

leetCode330:按要求補齊陣列

技術標籤:刷題筆記

目錄

一、題目描述

二、解題思路

三、程式碼實現


一、題目描述

給定一個已排序的正整數陣列 nums,和一個正整數n 。從[1, n]區間內選取任意個數字補充到nums中,使得[1, n]區間內的任何數字都可以用nums中某幾個數字的和來表示。請輸出滿足上述要求的最少需要補充的數字個數。

示例1:

輸入: nums = [1,3], n = 6
輸出: 1
解釋:
根據 nums裡現有的組合[1], [3], [1,3],可以得出1, 3, 4。
現在如果我們將2新增到nums 中,組合變為: [1], [2], [3], [1,3], [2,3], [1,2,3]。

其和可以表示數字1, 2, 3, 4, 5, 6,能夠覆蓋[1, 6]區間裡所有的數。
所以我們最少需要新增一個數字。

示例 2:

輸入: nums = [1,5,10], n = 20
輸出: 2
解釋: 我們需要新增[2, 4]。

示例3:

輸入: nums = [1,2,2], n = 5
輸出: 0

二、解題思路

難題恐怖就恐怖在沒有思路……根本不知道在考察什麼,連暴力都不知道該怎麼暴力。

看了題解之後稍微明白了一點,解題過程如下:

  • 本題考察的一個數學知識點其實很簡單:集合的加法運算[x, y] + a = [x+a, y+a],放到這道題裡就是如果已經覆蓋的範圍時[x, y],那麼再增加一個數a之後新的覆蓋範圍為[x+a, y+a]
  • 先看一個覆蓋範圍的情況:{1} =>[1, 1
    ],{1,2} =>[1, 3],{1,2,4} =>[1, 7],{1,2,4,8} =>[1, 15],{1,2,4,8,16} =>[1, 31],左邊表示陣列中的數字,右邊表示能覆蓋的範圍且可以用和的形式表示。注意每一組數加粗的部分。
  • 用nums[1, 2, 5], n = 20;來舉例:
  1. nums[1, 2, 5], n = 20;
  2. 首先初始狀態的覆蓋範圍為0,看第一個元素1,初始狀態加上1之後的覆蓋範圍變為[1, 1](此時我們希望接下來要新增的數字為2,因為需要保證覆蓋範圍可以用和的形式表示的連續性,且增加的數最少)
  3. 看第二個元素為2(等於我們的預期,不用額外增加數字),第2步中的覆蓋範圍加上2得到新的覆蓋範圍[1, 3](此時我們希望接下來要新增的數字為4);
  4. 看第三個元素為5(大於我們的預期),此時如果不增加額外的數字直接擴充套件範圍會得到[1,8]的範圍,但是不符合和表示的連續性,因為數字4不能使用和的形式來表示;所以我們需要新增額外的數字4,第2步中的覆蓋範圍加上4得到新的覆蓋範圍[1,7](接下來我們希望要新增的數字時8);
  5. 再看第三個元素5(小於我們的預期,不增加額外的數字),在第4步中的覆蓋範圍中加上5得到[1, 12](此時我們希望接下來新增的數字是13);
  6. 陣列中已經沒有元素,但是我們的覆蓋範圍還達不到要求,所以還需要新增數字13,在第5步中的範圍中加上13得到[1,25](此時我們希望接下來新增的數字時26);
  7. 陣列中已經沒有元素,且覆蓋範圍達到要求,過程中一共新增了2個數字,4和13。返回結果為2。

在實現時,我們初始希望新增的數字是1(初始的覆蓋範圍為[0, 0]),要注意這個細節。

三、程式碼實現

#include <bits/stdc++.h>
using namespace std;

int minPatches(vector<int>& nums, int n) {
	int length = nums.size();
	//用來記錄目前所能覆蓋的範圍,注意表示的範圍是[1, curr - 1];
    //初始範圍為[1,0]
	long long int curr = 1;
	//res為結果值,index為當前遍歷的下標值
	int res = 0, index = 0;
	while (curr <= n) {
		//陣列沒有完並且陣列當前值不大於curr值
		//表示當前最小的未被覆蓋的值是nums[index]
		if (index < length && nums[index] <= curr) {
			curr += nums[index];
			index++;
		} else {
			//否則表示覆蓋不具有連續性,需要先覆蓋到curr-1後面的值curr
			//覆蓋curr-1後面的數且滿足新增的數最少,即新增一個curr
			curr <<= 1;
			//新增一次,結果+1
			res++;
		}
	}
	return res;
}
int main() {
	vector<int> nums = { 1,5,10 };

	cout << minPatches(nums, 20) << " ";
	return 0;
}