當前位置:首頁 » 操作系統 » 原地演算法

原地演算法

發布時間: 2022-10-07 23:39:39

⑴ 傳動裝置的總效率計算

總效率η=運輸機傳送帶效率η1×運輸機軸承效率η2×運輸機與減速器間聯軸器效率η3×減速器內3對滾動軸承效率η4×2對圓柱齒輪嚙合傳動效率η5×電動機與減速器間聯軸器效率η6;

傳動系統的組成和布置形式是隨發動機的類型、安裝位置,以及汽車用途的不同而變化的。例如,越野車多採用四輪驅動,則在它的傳動系中就增加了分動器等總成。而對於前置前驅的車輛,它的傳動系中就沒有傳動軸等裝置。

(1)原地演算法擴展閱讀

汽車傳動系的基本功能就是將發動機發出的動力傳給驅動車輪。它的首要任務就是與汽車發動機協同工作,以保證汽車能在不同使用條件下正常行駛,並具有良好的動力性和燃油經濟性,為此,汽車傳動系都具備以下的功能:

減速和變速

我們知道,只有當作用在驅動輪上的牽引力足以克服外界對汽車的阻力時,汽車才能起步和正常行駛。由實驗得知,即使汽車在平直得瀝青路面上以低速勻速行駛,也需要克服數值約相當於1.5%汽車總重力得滾動阻力。

減速作用

為解決這些矛盾,必須使傳動系具有減速增距作用(簡稱減速作用),亦即使驅動輪的轉速降低為發動機轉速的若干分之一,相應地驅動輪所得到的扭距則增大到發動機扭距的若干倍。

⑵ 原地哈希演算法

原地哈希演算法主要應用在范圍為 [0, len(nums)] 的數組解法中,將數組元素本身作為 nums 的下標,即 nums[nums[i]] 。下面將結合leetcode 題目做一些總結。

題目描述:

題目分析:
首先想到的是利用哈希表來存儲數組中的元素,然後從 1 開始遍歷整數,不在哈希表中的第一個數字便是我們的解。我們知道了要從 1 開始遍歷,那遍歷到什麼值為止呢?
設數組的長度為 n ,如果數組中的元素正好為 [1, …, n] ,則缺失的元素為 n+1 ;如果數組中有非 [1, …, n] 的數字呢?則它們佔用的位置就是 [1, …, n] 中缺失的那些數字的位置。所以我們要找的數字一定是在 [1, …, n+1] 之間。所以我們需要遍歷的最大值為 n+1 。
題目要求使用常數級別的額外空間,而我們使用哈希表來存儲數字,空間復雜度為 O(n) ,不滿足要求。基於此,我們嘗試將原數組改造成哈希表(需要修改原數組,所以題目不能要求說不能修改原數組),這樣不使用額外的空間。
我們對數組進行遍歷,對於遍歷到的值 num ,如果它的值在 [1, n] 之間,那麼就將數組中索引為 num-1 的數字打上標記,在遍歷結束後,如果所有位置都被打上了標記,則答案為 n+1 ,否則為最小的沒有打上標記的位置加 1 。
由於我們只在意 [1, n] 中的數字,所以可以將其他數字做統一修改,比如改為 n+1 ,這樣數組中的數字都為正整數,也方便了我們使用數組中的元素作為索引來用。

題目描述:

題目分析:
首先想到利用哈希表統計計數便可以得出答案,時間和空間復雜度為 O(n) 。時間復雜度上的優化很難想到了,但是空間復雜度還是可能優化的。
長度為 n 的數組 nums 包含的數字為 [1, n] ,那顯然原地哈希演算法可以派上用場。
我們對數組進行遍歷,對於遍歷到的值 num ,就將數組中索引為 num-1 的數字打上標記,如果遍歷中發現某個數字已經被打上了標記,則表示這個數字為重復數字。遍歷完成後,除了丟失的數字對應的位置上的元素沒有標記,其餘數字都被打上了標記。

題目描述:

題目分析:
很容易想到利用哈希表來求解,但是哈希表的空間復雜度為 O(n) ,不滿足題目要求;基於上篇的位運算方法( https://www.jianshu.com/p/3b9a2a8a2e13 ),可以得到空間復雜度為 O(1) 的解。那麼除了位運算,是否還有其他滿足題目要求的解法呢?
既然數組中的數字都在 [1, n] 之間,那麼原地哈希演算法是否可以派上用場呢?
我們嘗試將數組中的元素作為索引來遍歷數組:
0 --> 1(nums[0]) --> 3(nums[1]) --> 2(nums[3]) --> 4(nums[2]) --> 2(nums[4])
我們發現重復數字 nums[3] 和 nums[4] 都指向了相同的數字 2 ,如果將上面的映射關系看做鏈表,那就是鏈表中出現了環: 2 --> 4 --> 2 ,且重復的數字剛好是環的入口節點的值。所以可以將題目轉換成求鏈表環的入口節點( https://leetcode-cn.com/problems/linked-list-cycle-ii/ )

⑶ 一個數據結構的問題,單鏈表原地逆置,他的演算法怎麼寫啊

Status reverse(LinkList &L) {
//L指向單鏈表的表頭,演算法將單鏈表逆轉,L指向逆轉後的表頭。
if (L==NULL ) return OK;
else if (L->next ==NULL) return OK;
p=L; q = p->next;
L->next = NULL;
while (q!=NULL){
Lnode * tem = q ->next;
q ->next = p;
p = q;
q = temp;
}
L = p;
return OK;
}
你看怎麼樣?

⑷ 矩陣置零

給定一個 m x n 的矩陣,如果一個元素為 0,則將其所在行和列的所有元素都設為 0。請使用原地演算法。

進階:

一個直接的解決方案是使用 O(mn) 的額外空間,但這並不是一個好的解決方案。
一個簡單的改進方案是使用 O(m + n) 的額外空間,但這仍然不是最好的解決方案。
你能想出一個常數空間的解決方案嗎?

咋一看,這個問題很簡單:直接遍歷整個矩陣,只要發現值為0的元素,就將其所在的行與列清零。不過這種方法有個缺陷:在讀取被清零的行與列時,讀到的盡是零,於是所在的行與所在的列都變成了0,很快,整個矩陣都變成了0.

避開這個缺陷的方法之一是新建一個矩陣標記零元素的位置。然後,在第二遍遍歷矩陣的時候將0元素所在的行與列清零。這種做法的空間復雜度為O(MN)

真的需要佔用O(MN)空間嗎?不是的,既然打算將整行和整列清零,因此並不需要標記錄它是cell[2][4](行2,列4),只需要知道行2有個元素為0,列4有個元素為0.不管怎樣,整行和整列都要清零,又何必要記錄零元素的確切位置?

常數空間的解決方案:
我們可以使用原矩陣的第一行和第一列來記錄哪些行和列需要全部置為0。
首先看第一行和第一列有沒有0,如果有,記錄flag表示之後第一行或第一列需要全部置為0;
遍歷除了第一行和第一列的所有元素,如果元素為0,則將其所在行與第一列交點的元素,其所在列與第一行交點的元素都置為0。
根據第一行和第一列中的0,將其他行列的元素置為0;
根據記錄的flag將第一行和第一列置為0。

⑸ 什麼是演算法原地工作的含義

演算法原地工作的含義是指不需要任何額外的輔助,演算法所需要的輔助空
間不隨著問題的規模而變化,是一個確定的值。
...

⑹ 請問求逆矩陣的原地求逆演算法,哪本書上有詳細的描述

用Gauss-Jordan法即可,
增廣矩陣A|E
初等行變換,變成E|B

求出A的逆矩陣是B

⑺ 快速排序特點

快速排序(Quicksort)是對冒泡排序的一種改進,由東尼·霍爾在1960年提出。 快速排序是指通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序。整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

分類
排序演算法

數據結構
不定

最壞空間復雜度
根據實現的方式不同而不同
快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。

步驟為:

從數列中挑出一個元素,稱為「基準」(pivot),

重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準後面(相同的數可以到任何一邊)。在這個分區結束之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。

遞歸地(recursively)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個演算法一定會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

在簡單的偽代碼中,此演算法可以被表示為:

function quicksort(q)
{
var list less, pivotList, greater
if length(q) ≤ 1
return q
else
{
select a pivot value pivot from q
for each x in q except the pivot element
{
if x<pivot then add x to less
if x ≥ pivot then add x to greater
}
add pivot to pivotList
return concatenate(quicksort(less), pivotList, quicksort(greater))
}
}
原地(in-place)分區的版本

上面簡單版本的缺點是,它需要的額外存儲空間,也就跟歸並排序一樣不好。額外需要的存儲器空間配置,在實際上的實現,也會極度影響速度和緩存的性能。有一個比較復雜使用原地(in-place)分區演算法的版本,且在好的基準選擇上,平均可以達到空間的使用復雜度。

function partition(a, left, right, pivotIndex)
{
pivotValue = a[pivotIndex]
swap(a[pivotIndex], a[right]) // 把pivot移到結尾
storeIndex = left
for i from left to right-1
{
if a[i]<= pivotValue
{
swap(a[storeIndex], a[i])
storeIndex = storeIndex + 1
}
}
swap(a[right], a[storeIndex]) // 把pivot移到它最後的地方
return storeIndex
}
這是原地分區演算法,它分區了標示為"左邊(left)"和"右邊(right)"的序列部分,藉由移動小於的所有元素到子序列的開頭,留下所有大於或等於的元素接在他們後面。在這個過程它也為基準元素找尋最後擺放的位置,也就是它回傳的值。它暫時地把基準元素移到子序列的結尾,而不會被前述方式影響到。由於演算法只使用交換,因此最後的數列與原先的數列擁有一樣的元素。要注意的是,一個元素在到達它的最後位置前,可能會被交換很多次。

一旦我們有了這個分區演算法,要寫快速排列本身就很容易:

procere quicksort(a, left, right)
if right>left
select a pivot value a[pivotIndex]
pivotNewIndex := partition(a, left, right, pivotIndex)
quicksort(a, left, pivotNewIndex-1)
quicksort(a, pivotNewIndex+1, right)
這個版本經常會被使用在命令式語言中,像是C語言。

快速排序
快速排序是二叉查找樹(二叉搜索樹)的一個空間最優化版本。不是循序地把數據項插入到一個明確的樹中,而是由快速排序組織這些數據項到一個由遞歸調用所隱含的樹中。這兩個演算法完全地產生相同的比較次數,但是順序不同。對於排序演算法的穩定性指標,原地分區版本的快速排序演算法是不穩定的。其他變種是可以通過犧牲性能和空間來維護穩定性的。

⑻ 為什麼選C,我感覺3有問題啊,不是上界吧

(1)是不對的 《數據結構》嚴蔚敏版說:「若額外空間相對於輸入數據量來說是常數」則稱此演算法為原地工作。
(2)可以算對,但是描述有個概念性問題:演算法復雜度是沒有常數的,即沒有O(2n)這樣的說法。你在執行每一條語句的時候比如加和乘,所消耗的時間都不一樣,不要加常數加以限制。
(3)是正確的,比如下面演算法
if(n>1000)
for(int i=0;i<n;i++)
a++;
else
a=0;
中不考慮else里的時間了,時間復雜度應該是O(n)
(4)對於第四項肯定是錯誤的。
所以選C (1)和(4)
(想選1 2 4)

⑼ 堆和堆排序

1,堆是一個完全二叉樹;
完全二叉樹要求除了最後一層,其他層的節點都是滿的,最後一層的節點都靠左排列。
2,堆中每個節點都必須大於等於(或小於等於)其子樹中每個節點的值。
堆中每個節點的值都大於等於(或者小於等於)其左右子節點的值。
3,對於每個節點的值都大於等於子樹中每個節點值的堆,叫作「大頂堆」。對於每個節點的值都小於等於子樹中每個節點值的堆,叫「小頂堆」。

要實現一個堆,要先知道堆都支持哪些操作,已及如何存儲一個堆。
1,如何存儲一個堆:
完全二叉樹比較適合用數組來存儲。用數組來存儲完全二叉樹是非常節省存儲空間的。因為不需要存儲左右子節點的指針,單純地通過數組的下標,就可以找到一個節點的左右子節點和父節點。
2,往堆中插入一個元素
往堆中插入一個元素後,需要繼續滿足堆的兩個特性
(1)如果把新插入的元素放到堆的最後,則不符合堆的特性了,於是需要進行調整,讓其重新滿足堆的特性,這個過程叫做 堆化(heapify)
(2)堆化實際上有兩種,從下往上和從上往下
(3)從下往上的堆化方法:
堆化非常簡單,就是順著節點所在的路徑,向上或者向下,對比,然後交換。

(1)從堆的定義的第二條中,任何節點的值都大於等於(或小於等於)子樹節點的值,則堆頂元素存儲的就是堆中數據的最大值或最小值。
(2)假設是大頂堆,堆堆頂元素就是最大的元素,但刪除堆頂元素之後,就需要把第二大元素放到堆頂,那第二大元素肯定會出現在左右子節點中。然後在迭代地刪除第二大節點,以此類推,直到葉子節點被刪除。

但這種方式會使堆化出來的堆不滿足完全二叉樹的特性
(3)可以把最後一個節點放到堆頂,然後利用同樣的父子節點對比方法,對於不滿足父子節點大小關系的,互換兩個節點,並且重復進行這個過程,直到父子節點之間滿足大小關系為止,這是從上往下的堆化方法。

一個包含n個節點的完全二叉樹,樹的高度不會超過log2n。堆化的過程是順著節點所在路徑比較交換的,所以堆化的時間復雜度跟樹的高度成正比,即O(log n)。插入數據和刪除堆頂元素的主要邏輯就是堆化,所以往堆中插入一個元素和刪除堆頂元素的時間復雜度都是O(log n)。

(1)排序方法有時間復雜度是O(n^2)的冒泡排序,插入排序,選擇排序,有時間復雜度是O(nlogn)的歸並排序,快速排序,線性排序。

(2)藉助堆這種數據結構實現的排序演算法就叫作堆排序,這種排序方法的時間復雜度非常穩定,是O(nlogn),並且它還是原地排序演算法。
堆排序的過程大致分解為兩大步驟:建堆和排序
(3)建堆:
1,首先將數組原地建成一個堆。「原地」:是指不藉助另一個數組,就在原地數組上操作。
2,建堆有兩種思路:
第一種:在堆中插入一個元素的思路。
盡管數組中包含n個數據,但是可以假設起初堆中只包含一個數據,就是下標為1的數據。然後,調用插入方法,將將下標從2到n的數據依次插入到堆中,這樣就將包含n個數據的數組,組織成了堆
第二種:是從後往前處理數組,並且每個數據都是從上往下堆化。
第二種和第一種思路截然相反,第一種建堆思路的處理過程是從前往後處理數據,並且每個數據插入堆中時,都是從下往上堆化。
對下標從n/2開始到1的數據進行堆化,下標是n/2 + 1到n的節點,是葉子節點,不需堆化
3,建堆的時間復雜度
每個節點堆化的時間復雜度是O(logn),則n/2+1個節點堆化的總時間復雜度是O(n)。
①:因為葉子節點不需要堆化,所以需要堆化的節點從倒數第二層開始。每個節點堆化的過程中,需要比較和交換的節點個數,跟這個節點高度k成正比。
(4)排序:
建堆結束後,數組中的數據已是按照大頂堆的特性來組織的。數組中的第一個元素就是堆頂,也就是最大的元素。
將它和最後一個元素交換,最大元素就放到了下標為n的位置
這個過程有點類似「刪除堆頂元素」的操作,當堆頂元素移除後,把下標為n的元素放到堆頂,然後在通過堆化的方法,將剩下的n-1個元素重新構建成堆。堆化完成之後,在取堆頂元素,放到下標是n-1的位置,一直重復這個過程,直到最後堆中只剩下標為1的一個元素,排序工作就完成了。

(5)時間,空間復雜度,以及穩定性分析
①:整個堆排序的過程,都只需要極個別臨時存儲空間,所以堆排序是原地排序演算法。
②:堆排序包括建堆和排序兩個操作,建堆過程的時間復雜度是O(n),排序過程的時間復雜度是O(nlogn),所以堆排序的時間復雜度是O(nlogn)
③:堆排序不是穩定的排序演算法,可能改變值相等的數據原始相對順序。

熱點內容
大華錄像機哪裡有安卓設備 發布:2025-05-15 14:25:06 瀏覽:806
錄制腳本方案 發布:2025-05-15 14:25:04 瀏覽:164
奇石腳本業 發布:2025-05-15 14:23:44 瀏覽:678
android中的socket 發布:2025-05-15 14:22:15 瀏覽:407
apph5源碼 發布:2025-05-15 14:19:51 瀏覽:664
2d游戲按鍵精靈腳本教程 發布:2025-05-15 14:10:15 瀏覽:278
伺服器上的郵件如何銷毀 發布:2025-05-15 14:02:49 瀏覽:137
飢荒安卓版如何解除手柄模式 發布:2025-05-15 14:02:05 瀏覽:112
演算法強化班 發布:2025-05-15 14:02:04 瀏覽:345
c語言編譯後圖片 發布:2025-05-15 13:51:57 瀏覽:792