《盤點那些秀你一臉的秒天秒地算法》(1)

本系列堅持格式:1個抖機靈算法+2個較簡單但是天秀的算法+1個較難天秀算法。

?

bogo排序

Bogo排序(Bogo-sort),又被稱為猴子排序,是一種惡搞排序算法。

將元素隨機打亂,然后檢查其是否符合排列順序,若否,則繼續進行隨機打亂,繼續檢查結果,直到符合排列順序。
Bogo排序的最壞時間復雜度為O(∞),一輩子也不能輸出排序結果,平均時間復雜度為O(n·n!)。

這讓我想到了另一個理論:猴子理論,只要讓一只猴子一直敲打計算機,理論上會有一天,它能敲出一本圣經出來,但是這個概率小到宇宙毀滅也很難敲出來。。

真的不知道這個排序應該叫做天才還是垃圾哈哈哈,但是閑的沒事的我就把他實現出來了。

public class Main {public static void main(String[] args) {int[] arr = { 9,8,7,6,5,4,3,2,1};System.out.println("排序次數" + bogo(arr));for (int i : arr) {System.out.print(i + " ");}}public static int bogo(int[] arr) {int count = 0;while (!isOrdered(arr)) {shuffle(arr);count++;}return count;}// 判斷是否有序方法public static boolean isOrdered(int[] arr) {for (int i = 1; i < arr.length; i++) {if (arr[i - 1] > arr[i]) {return false;}}return true;}// 隨機排序方法public static void shuffle(int[] arr) {int temp;for (int i = 0; i < arr.length; i++) {int j = (int) (Math.random() * arr.length);temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}

9是中國最大的數字嘛,我就把數組長度設為9,結果平均排序次數要60萬次,不知道我的運氣怎么樣哈哈,你們也試試吧?

?

然而,有個看似笑話的方法聲稱可以用O(n)實現Bogo排序,依照量子理論的平行宇宙解釋,使用量子隨機性隨機地重新排列元素,不同的可能性將在不同的宇宙中展開,總有一種可能猴子得到了正確的順序,量子計算機找到了這個宇宙后,就開始毀滅其他排序不成功的宇宙,剩下一個觀察者可以看到的正確順序的宇宙。

如果想要邁出這個看似荒誕,但令人無比興奮的"高效算法"的第一步,請先證明"平行宇宙解釋"的正確性。

位運算

關于位運算有很多天秀的技巧,這里舉一個例子。

給定一個非空整數數組,除了某個元素只出現一次以外,其余每個元素均出現兩次。找出那個只出現了一次的元素。

說明:你的算法應該具有線性時間復雜度。 你可以不使用額外空間來實現嗎?

示例 1:

輸入: [2,2,1]輸出: 1
示例?2:

輸入: [4,1,2,1,2]輸出: 4

思路:拿map,set,都不符合要求,那怎么辦呢?

我們知道什么數字和自己異或,都等于0.

什么數字和0異或,都等于它本身,

異或又符合交換律

所以全部異或一遍,答案就是那個出現一次的數字。

class Solution {public int singleNumber(int[] nums) {int ans = 0;for(int i :nums)ans ^= i;return ans;}
}

有沒有被秒了?

?

打擂臺

給定一個大小為 n 的數組,找到其中的多數元素。多數元素是指在數組中出現次數大于?? n/2 ??的元素。

你可以假設數組是非空的,并且給定的數組總是存在多數元素。

把狂野般的思緒收一收,咱們來看看最優解。

class Solution {public int majorityElement(int[] nums) {int count = 0;//當前答案出現的次數Integer candidate = null;//答案for (int num : nums) {if (count == 0) candidate = num;count += (num == candidate) ? 1 : -1;}return candidate;}
}

我來解釋一下策略:記錄當前的答案candidate ,記錄count。這時,我們遍歷了一個新的數字,如果和candidate 一樣,我們就讓count+1,否則讓count-1.如果count變成了0,那candidate 就下擂臺,換新的擂主(數字)上,也就是說把candidate 更新成新的數字,count也更新成1.

最后在擂臺上的一定是答案。

肯定有人懷疑這個做法的正確性吧?我就來說一下它為啥對?

首先,我們想像一下對最終隱藏答案ans最不利的情況:每個其他數字全部都打擂這個答案ans,那ans的count最后也會剩1,不會被打下來。

正常情況呢?其他數字還會互相打擂,這些數字如此“內耗”,又怎么能斗得過最終答案ans呢?對不對?

?

morris遍歷

通常,實現二叉樹的前序(preorder)、中序(inorder)、后序(postorder)遍歷有兩個常用的方法:一是遞歸(recursive),二是使用棧實現的迭代版本(stack+iterative)。這兩種方法都是O(n)的空間復雜度(遞歸本身占用stack空間或者用戶自定義的stack),我分別給出一個例子

遞歸:

void PreorderTraversal( BinTree BT )
{if(BT==NULL)return ;printf(" %c", BT->Data);PreorderTraversal(BT->Left);PreorderTraversal(BT->Right);
}

非遞歸:

*p=root;
while(p || !st.empty())
{if(p)//非空{//visit(p);進行操作st.push(p);//入棧p = p->lchild;左} else//空{p = st.top();//取出st.pop();p = p->rchild;//右}
}

為啥這個O(n)的空間就是省不掉呢?因為我們需要空間來記錄之前的位置,好在遍歷完了可以回到父節點。所以這個空間是必須的!如下圖:

比如我們遍歷2,想遍歷4,這時候我們要保證遍歷完4以后,還能回到2,我們好去繼續遍歷5等等結點,所以必須花空間記錄。

?

但是,還就有這么一種算法,能實現空間O(1)的遍歷,服不服。

你們可能會問,你剛說的,必須有空間來記錄路徑,怎么又可以不用空間了呢?

這就是morris遍歷,它其實是利用了葉子節點大量的空余空間來實現的,只要把他們利用起來,我們就可以省掉額外空間啦。

我們不說先序中序后序,先說morris遍歷的原則:

1、如果沒有左孩子,繼續遍歷右子樹,比如:

這個2就沒有左孩子,這時直接遍歷右孩子即可。

2、如果有左孩子,找到左子樹最右節點。

比如上圖,6就是2的最右節點。

? ? 1)如果最右節點的右指針為空(說明第一次遇到),把它指向當前節點,當前節點向左繼續處理。

修改后:

? ? 2)如果最右節點的右指針不為空(說明它指向之前結點),把右指針設為空,當前節點向右繼續處理。

?

這就是morris遍歷。

請手動模擬深度至少為4的樹的morris遍歷來熟悉流程。

下面給出實現:

定義結點:

	public static class Node {public int value;Node left;Node right;public Node(int data) {this.value = data;}}

先序:(完全按規則寫就好。)

//打印時機(第一次遇到):發現左子樹最右的孩子右指針指向空,或無左子樹。public static void morrisPre(Node head) {if (head == null) {return;}Node cur1 = head;Node cur2 = null;while (cur1 != null) {cur2 = cur1.left;if (cur2 != null) {while (cur2.right != null && cur2.right != cur1) {cur2 = cur2.right;}if (cur2.right == null) {cur2.right = cur1;System.out.print(cur1.value + " ");cur1 = cur1.left;continue;} else {cur2.right = null;}} else {System.out.print(cur1.value + " ");}cur1 = cur1.right;}System.out.println();}

morris在發表文章時只寫出了中序遍歷。而先序遍歷只是打印時機不同而已,所以后人改進出了先序遍歷。至于后序,是通過打印所有的右邊界來實現的:對每個有邊界逆序,打印,再逆序回去。注意要原地逆序,否則我們morris遍歷的意義也就沒有了。

完整代碼:?

public class MorrisTraversal {public static void process(Node head) {if(head == null) {return;}// 1//System.out.println(head.value);process(head.left);// 2//System.out.println(head.value);process(head.right);// 3//System.out.println(head.value);}public static class Node {public int value;Node left;Node right;public Node(int data) {this.value = data;}}//打印時機:向右走之前public static void morrisIn(Node head) {if (head == null) {return;}Node cur1 = head;//當前節點Node cur2 = null;//最右while (cur1 != null) {cur2 = cur1.left;//左孩子不為空if (cur2 != null) {while (cur2.right != null && cur2.right != cur1) {cur2 = cur2.right;}//找到最右//右指針為空,指向cur1,cur1向左繼續if (cur2.right == null) {cur2.right = cur1;cur1 = cur1.left;continue;} else {cur2.right = null;}//右指針不為空,設為空}System.out.print(cur1.value + " ");cur1 = cur1.right;}System.out.println();}//打印時機(第一次遇到):發現左子樹最右的孩子右指針指向空,或無左子樹。public static void morrisPre(Node head) {if (head == null) {return;}Node cur1 = head;Node cur2 = null;while (cur1 != null) {cur2 = cur1.left;if (cur2 != null) {while (cur2.right != null && cur2.right != cur1) {cur2 = cur2.right;}if (cur2.right == null) {cur2.right = cur1;System.out.print(cur1.value + " ");cur1 = cur1.left;continue;} else {cur2.right = null;}} else {System.out.print(cur1.value + " ");}cur1 = cur1.right;}System.out.println();}//逆序打印所有右邊界public static void morrisPos(Node head) {if (head == null) {return;}Node cur1 = head;Node cur2 = null;while (cur1 != null) {cur2 = cur1.left;if (cur2 != null) {while (cur2.right != null && cur2.right != cur1) {cur2 = cur2.right;}if (cur2.right == null) {cur2.right = cur1;cur1 = cur1.left;continue;} else {cur2.right = null;printEdge(cur1.left);}}cur1 = cur1.right;}printEdge(head);System.out.println();}
//逆序打印public static void printEdge(Node head) {Node tail = reverseEdge(head);Node cur = tail;while (cur != null) {System.out.print(cur.value + " ");cur = cur.right;}reverseEdge(tail);}
//逆序(類似鏈表逆序)public static Node reverseEdge(Node from) {Node pre = null;Node next = null;while (from != null) {next = from.right;from.right = pre;pre = from;from = next;}return pre;}public static void main(String[] args) {Node head = new Node(4);head.left = new Node(2);head.right = new Node(6);head.left.left = new Node(1);head.left.right = new Node(3);head.right.left = new Node(5);head.right.right = new Node(7);morrisIn(head);morrisPre(head);morrisPos(head);}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444702.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444702.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

caffe安裝篇(一)

caffe我選擇使用ubuntu源碼安裝,所以先執行: sudo apt-get install -y libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libboost-all-dev protobuf-compiler libhdf5-serial-dev sudo apt-get install -y libgflags-dev libgoogle-glog-dev liblmdb-dev prot…

caffe2安裝篇(三)通過docker安裝

用普通的安裝方式走了不少彎路,感覺還是用docker方便: 參考的是https://hub.docker.com/r/caffe2ai/caffe2/ Latest docker pull caffe2ai/caffe2 Comes with GPU support, CUDA 8.0, cuDNN 7, all options, and tutorial files. Uses Caffe2 v0.8.1. GPU images (for us…

《盤點那些秀你一臉的秒天秒地算法》(3)

斐波那契之美 斐波那契數列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又稱黃金分割數列、因數學家列昂納多斐波那契&#xff08;Leonardoda Fibonacci&#xff09;以兔子繁殖為例子而引入&#xff0c;故又稱為“兔子數列”。 這個數列就是1、1、2、3、5、8、13…

Linux(15)-

Linux下的編程開發

《盤點那些秀你一臉的秒天秒地算法》(4)

防止新手錯誤的神級代碼 #define ture true #define flase false #difine viod void #define mian main #define &#xff1b; ; 以后有新手問題就把這幾行代碼給他就好啦。 不用額外空間交換兩個變量 a 5 b 8 #計算a和b兩個點到原點的距離之和&#xff0c;并且賦值給…

Linux(16)-

Vim編輯器的使用

php生成有復雜結構的excel文檔

以前都用PHPExcel等工具來生成Excel&#xff0c;但是我們有時候需要非常復雜的樣式&#xff0c;比如有合并單元格和拆分單元格&#xff0c;甚至有顏色&#xff0c;行間距之類的&#xff0c;這樣做起來很費勁&#xff0c;而且你如果使用插件&#xff0c;你也需要學習這里我們可以…

caffe2安裝篇(二) ubuntu16.04 安裝方法

caffe2 ubuntu16.04 安裝方法 Caffe2的安裝相比于caffe在安裝的時候更加簡便,略去了Makefile.config的各種配置,對于有無GPU以及各種可選庫例如opencv,anaconda的支持也更簡單。(其實你直接裝好庫以后make就好,以GPU為例,在make的時候,自動檢測你是否安裝了CUDA,若沒有…

為啥用redis解決會話呢?

什么是會話&#xff1f; 會話可簡單理解為&#xff1a;用戶開一個瀏覽器&#xff0c;點擊多個超鏈接&#xff0c;訪問服務器多個web資源&#xff0c;然后關閉瀏覽器&#xff0c;整個過程稱之為一個會話。 ?會話過程中要解決的一些問題&#xff1f; –每個用戶不可避免各自會…

推薦系統(5)-深度推薦模型-AutoRec、DeepCrossing、NeuralCF、PNN、WideDeep、FNN、DeepFM、NFM

GBDTLR1. AutoRec-20152. Deep Crossing-20163. NeuralCF-20164. PNN-20165. Wide&Deep-20166. Deep&Cross-20177.FM深度學習7.1 FNN-20167.2 DeepFM-20177.3 NFM-2017《深度學習/推薦系統》讀書筆記2016年開始&#xff0c;推薦系統和計算廣告全面進入深度學習時代。 &…

關于在安裝caffe2環境中遇到的坑整理(歡迎入坑討論)

1.ImportError: cannot import name caffe2_pb2 測試caffe2的pytorch環境是否正常的時候使用 root@lxsj-ThinkStation:~/pytorch# python Python 2.7.12 (default, Dec 4 2017, 14:50:18) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", &…

leetcode172. 階乘后的零 最快算法

給定一個整數 n&#xff0c;返回 n! 結果尾數中零的數量。 示例 1: 輸入: 3 輸出: 0 解釋: 3! 6, 尾數中沒有零。 示例 2: 輸入: 5 輸出: 1 解釋: 5! 120, 尾數中有 1 個零. 說明: 你算法的時間復雜度應為 O(log n) 。 思路&#xff1a;102*5&#xff0c;而因數中2一定比…

Win10 連接 Ubuntu16.04.3(通過Xdrp連接xfce4界面)

Win10 連接 Ubuntu16.04.3(通過Xdrp連接xfce4界面) sudo apt-get install xrdp sudo apt-get install vnc4server sudo apt-get install xubuntu-desktop echo "xfce4-session" >~/.xsession sudo apt-get install dconf editor sudo dconf editor(或者在搜索…

Linux(17)-

Make編譯機制,Configure

聽說你還在糾結自己沒訪問量?成不了“博客專家”?

一、提高瀏覽量的技巧 相信很多人都這么想過&#xff1a;“我文章寫的這么好&#xff0c;怎么就沒人看呢&#xff1f;”&#xff1b; 或者這樣想過&#xff1a;“這文章寫得明明比我爛很多&#xff0c;憑什么這么多瀏覽量&#xff1f;”&#xff1b; 雖然在我看來這是極其嚴…

推薦系統(6)-注意力機制+深度推薦模型、強化學習推薦系統

注意力機制深度推薦模型、強化學習推薦系統1.AFM -20172.DIN-20173.DIEN-20194. DRN-20181.AFM -2017 Attention factorization machines–浙江大學–基于模型結構的改進 引入注意力機制FM&#xff0c; 可視為NFM模型的改進。給特征交叉池化后的特征向量施加不同的注意力權重。…

Caffe安裝的坑整理

怎么說了,入了深度學習的坑,就要踩一踩才算你入門,這里我整理了我在安裝學習caffe自己遇到的坑: 1.Caffe-GPU編譯問題:nvcc fatal : Unsupported gpu architecture compute_20 仔細查看了一下 Makefile.config 中 CUDA_ARCH 設置未按規定設置: # CUDA architecture se…

leetcode74. 搜索二維矩陣 ,你見過嗎

編寫一個高效的算法來判斷 m x n 矩陣中&#xff0c;是否存在一個目標值。該矩陣具有如下特性&#xff1a; 每行中的整數從左到右按升序排列。 每行的第一個整數大于前一行的最后一個整數。 示例 1: 輸入: matrix [ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34,…

pytorch學習 入門篇(一)

PyTorch 是什么? 它是一個基于 Python 的科學計算包, 其主要是為了解決兩類場景: NumPy 的替代品, 以使用 GPU 的強大加速功能一個深度學習研究平臺, 提供最大的靈活性和速度Tensors(張量) Tensors 與 NumPy 的 ndarrays 非常相似, 除此之外還可以在 GPU 上使用張量來加速…

關系數據庫——范式/反范式的利弊權衡和建議

范式&#xff08;避免數據冗余和操作異常&#xff09; 函數依賴 A->B A和B是兩個屬性集&#xff0c;來自同一關系模式&#xff0c;對于同樣的A屬性值&#xff0c;B屬性值也相同 平凡的函數依賴 X->Y&#xff0c;如果Y是X的子集 非平凡的函數依賴 X->Y&#xff…