ap325第六天
跳躍式二分搜基本寫法
- 本段為找到第一個大於x的位置
1
2
3
4
5
6
7
8
9
10int jump_search(int a[],int n,int x){
if(a[0]>=x) return 0;
int po=0;
for(int jump=n/2;jump>0;jump/=2){
while(po+jump<n && a[po+jump]<x){
po+=jump;
}
}
return po+1;
}
C++函數
binary_search()
lower_bound()
upper_bound()
其實只要學會使用lower_bound(),這個函數是用來找到第一個大於等於某個值的位
置,另外兩個都很像,upper_bound()找到第一個大於某值的位置,而
binary_search()是只傳回是否找到。
lower_bound(first, last, t);
要求在[first, last)
的範圍內以二分搜找到第一個大於或等於t的值,找到時回傳
所在位置,找不到時(t比最後一個大),回傳last。以下有幾點請注意:
- 找到時回傳的是位置,要得到陣列索引值就將它減去陣列起始位置。
- 呼叫
lower_bound()
必須確定搜尋範圍是排好序的,如果你針對亂七八糟的資料
以lower_bound()
去進行二分搜,只會得到亂七八糟的結果,編譯器是不會告訴
你沒排序的。 - 搜尋範圍是傳統的左閉右開區間,也就是不含last;
- 找不到時回傳last,通常這個位置是超過陣列的範圍,所以沒確定找到時不可以
直接去引用該位置的值。
例題2-2
https://judge.tcirc.tw/problem/d011
自己寫的解:
1 |
|
教科書解:
1 |
|
- 答案細節:
C++ 中,陣列作為函數參數時,是以指標形式傳遞的。也就是說,當你將 b 作為參數傳入函數 distinct() 時,實際上傳遞的是 b 的記憶體地址。因此,distinct() 函數內對 b 陣列的操作會直接修改原來的 b 陣列的內容。
所以b會自動改變。
用map實作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using namespace std;
typedef long long LL;
int main()
{
int a[N],n,k;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
map<int,int> S; //map第一位是key,第二位是值 first,second
for(int i=0;i<n;i++){
S[a[i]]=0;
}
int r=0;
for(auto it=S.begin();it!=S.end();++it){ //it是迭代器,指向 map 中的每個鍵值對。
it->second=r++;
}
for(int i=0;i<n;i++){
a[i]=S.find(a[i])->second;
}
for(int i=0;i<n;i++){
cout<<a[i]<<' ';
}
return 0;
}
關於stl資料結構(DS)
https://zrn-code.github.io/2020/07/18/STL/
2-3快速冪
https://judge.tcirc.tw/problem/d012
最簡單寫法:
1 |
|
但實在跑太慢拉~
運用分治、遞迴把它優化一下:
O(y)->O(log y)
1 |
|
2-4快速冪200位
https://judge.tcirc.tw/problem/d013
1 |
|
當x大到超過long long的時候,我們需要先求x除以p的餘
數,而除以p的餘數可以一位一位的累加計算。例如x=123, p=5,x可以看成
(1*10+2)10+3,所以x除以p的餘數也就等於
((((110%p+2)%p)*10)%p+3)%p。
所以要邊把string轉成int邊mod
2-6Two-Number problem
https://judge.tcirc.tw/problem/d015
用二分搜加速搜尋速度以A的元素在B中滑動找解
1 |
|
順便附上剛剛寫的leetcode minimize-xor
https://leetcode.com/problems/minimize-xor/
這題可以練習bit運算1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60class Solution {
public:
long long result;
void cmp(int total1, int total2, vector<int> v) {
if (total1 == total2) {
long long i = 1;
while (!v.empty()) {
result += i * v.back();
i *= 2;
v.pop_back();
}
return;
}
if (total1 > total2) {
for (int i = v.size() - 1; i >= 0; i--) {
if (v[i] == 1) {
v[i] = 0;
cmp(total1 - 1, total2, v);
break;
}
}
/*for (auto &t : v) {
if (t == 1) {
t = 0;
cmp(total1 - 1, total2, v);
break;
}
}*/
} else if (total1 < total2) {
for (int i = v.size() - 1; i >= 0; i--) {
if (v[i] == 0) {
v[i] = 1;
cmp(total1 + 1, total2, v);
break;
}
}
}
}
int minimizeXor(int num1, int num2) {
result = 0;
int total1 = 0;
int total2 = 0;
while (num2 > 0) {
total2 += num2 % 2;
num2 /= 2;
}
vector<int> v;
while (num1 > 0) {
total1 += num1 % 2;
v.push_back(num1 % 2);
num1 /= 2;
}
reverse(v.begin(), v.end());
while (v.size() < 32) {
v.insert(v.begin(), 0);
}
cmp(total1, total2, v);
return result;
}
};leetcode動態規劃、遞迴
https://leetcode.com/problems/combination-sum-iv/
我的菜菜寫法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Solution {
public:
int recursion(int n, vector<int> nums, vector<int>& dp) {
if (n < 0) {
return 0;
}
if (n == 0) {
return 1;
}
if (dp[n] != -1) {
return dp[n]; // 如果已經計算過,直接返回結果
}
int result = 0;
for (auto k : nums) {
result += recursion(n - k, nums, dp); // 累加所有可能的結果
}
dp[n] = result; // 記錄計算結果以提高效率
return result;
}
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1, -1); // 動態規劃數組,初始化為 -1
return recursion(target, nums, dp);
}
};動態規劃更強的寫法:
1
2
3
4
5
6
7
8
9
10
11
12
13class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<unsigned int> dp(target+1,0);
dp[0]=1;
for(int i=1;i<=target;i++){
for(int j:nums){
if(i-j>=0) dp[i]+=dp[i-j];
}
}
return dp[target];
}
};外層迴圈:
for(int i = 1; i <= target; i++)
,表示我們從 1 一直計算到target
,對每個目標值i
,我們都試圖通過減去 nums 中的數字來達到這個目標。
內層迴圈:for(int j : nums)
,表示對於nums
中的每一個數字j
,如果i - j >= 0
,即當i - j
是有效的(不小於 0)時,我們將dp[i - j]
的值加到dp[i]
上。
這是因為,如果我們可以從i - j
達到i
,那麼所有能達到i - j
的組合都可以通過再加上j
來達到i
。