1. 程式人生 > 其它 >3月23號學習總結

3月23號學習總結

  1. 二分查詢
    二分查詢的前提:有序陣列(無序陣列可以通過sort函式實現)

二分查詢的時間複雜度是\(O(logn)\),順序查詢的時間複雜度是\(O(n)\)

二分查詢的思想很簡單,開始的時候演算法定義兩個指標left和right分別指向陣列的頭和尾,當left與right沒有相撞(\(<=\))時,執行下述操作:計算\(pos=(right+left)/2\),將位於pos的元素與left和right的元素進行比較,如果nums[pos]>target,那麼證明元素可能存在的位置位於pos之前,所以我們令\(right=pos\);同樣的,如果nums[pos]<target,那麼證明元素可能存在的位置位於pos之後,所以我們令\(left=pos\)

;而如果相等,則我們找到我們所需要的元素,直接返回即可。如果當迴圈結束時我們沒有找到,則證明該元素不存在於陣列中,演算法結束。

二分查詢有普通迴圈和遞迴兩種寫法,建議適應普通迴圈寫法,這樣當陣列數目很大時我們不會瘋狂開闢空間導致記憶體爆炸。

#include<bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
int BinarySearch(vi a, int target)
{
	int left = 0;
	int right = a.size()-1;
	while (left <= right)
	{
		int pos = (left + right) / 2;
		if (a[pos] > target)
		{
			right = pos-1;
		}
		else if (a[pos] < target)
		{
			left = pos+1;
		}
		else
		{
			return pos;
		}
	}
	return -1;
}

int BinarySearchR(vi a, int target)
{	
	static vi posplus = {};
	int left = 0;
	int right = a.size() - 1;
	int pos = (left + right) / 2;
	if (left > right)
	{
		return -1;
	}
	if (a[pos] == target)
	{
		return pos+accumulate(posplus.begin(),posplus.end(),0);
	}
	else if (a[pos] < target)
	{	
		posplus.push_back(pos+1);
		vi b (a.begin()+pos+1, a.end());
		return BinarySearchR(b, target);
	}
	else
	{
		vi b (a.begin(),a.begin() + pos);
		return BinarySearchR(b, target);
	}
	
}

int main()
{
	vi a = { 1,4,5,7,8,9,10 };
	int target = 8;
	int answer = BinarySearchR(a, target);
	cout << answer;
}
  1. 資料結構與演算法第二章演算法分析
    內容摘要:

*如何估計一個程式所需要的時間?(計算時間複雜度)

*如何降低時間複雜度?

*盲目使用遞迴的後果

在函式之間建立一種相對的級別,也就是說我們不關注函式在某點具體的數值大小,而是關注相對增長率。

需要掌握的重要結論:對任意常數k,\(log^kN=O(N)\),對數增長得非常緩慢。

計算大O得一般法則:

  1. for迴圈

一個for迴圈的執行時間至多是該for迴圈內部那些語句(包括測試)的執行時間乘以迭代的次數。

  1. 巢狀的迴圈

從裡向外分析這些迴圈。在一組巢狀迴圈內部的一條語句總的執行時間為該語句的執行時間乘以該組所有的for迴圈的大小的乘積。

  1. 順序語句

將各個語句的執行時間求和即可。

  1. if/else語句
    挑選其中執行時間較高的一個作為程式碼塊的執行時間。