演算法設計與分析 第三週
題目描述
選題原因
之前兩週做了兩道
中等
難度的題目,結果還算不錯,因此這次準備選一道困難
的題目。篩選了圖演算法
,開始選了一道冗餘連線II
,完成之後發現題目有一些bug
。當選擇的時候,題目要求有多條邊冗餘的時候需要選擇先出現的邊,但是實際測試的時候並不是以這樣的標準。因此放棄了冗餘連線II
,重新選擇了這一題情侶牽手
。
題目分析
突然一看,這一題彷彿和
圖演算法
沒有什麼關係。但是實際上這道題的核心就是有環圖
。
我們先來看看這一題怎麼解。在觀察這道題的時候不難會產生疑問:當我們交換的座位順序不同的時候會不會對結果有影響?這樣得到的結果還是最少次數嗎?
但是結合有環圖
的思想來看,最優的解法就是不停的讓一個人離開,去找她的伴侶。
想要理解,我們需要用有環圖
的思想來類比。
我們把每兩個相鄰的座位看作一個節點
(0,1或2,3這樣的),而如果兩個座位換了的話,就看做兩個節點有聯絡,我們就用一條邊
來把他們連線起來。
下面,我們需要理解兩個思想:
- 一個人出去找座位開始,直到找到的剛好是自己的情侶為終止,可以構成一條單鏈。
- 相鄰兩條單鏈如果連線,會使步驟增加。
從一條單鏈任意節點開始,最後需要的步數相同。
我們還是按照原有的思想,先找出一條單鏈。
若是我們改為從B節點出發,那麼結果會是這樣
很容易發現,只要是從這一條路上開始,無論哪一個節點,最後都會使用相同的步驟到達終點。(可以試著構造一條虛環,便於理解)
相鄰兩條單鏈連線會使得消耗更多的步驟
這一條理解起來就有些困難了,那就讓我們引入一些概念:假設A節點一對情侶為a1, a2; 同理,B節點情侶為b1, b2。
讓我們構造兩條不相關的單鏈。
如果我們將他們首尾相連,交換他們的元素,那麼會發生什麼情況?
我們驚奇的發現,他們連成了一條線?為什麼會這樣呢?其實很容易理解:我們將節點裡的每一個元素看成一個連線因子,當兩條鏈的連線因子交換了之後,兩條鏈就必然產生聯絡;而每一條原本都是獨立的,當一個因子交換出去了之後,也只會有一個元素需要和外界連線,如此一來,就會構成一條鏈。
但這樣,步數增加了多少?2
步。
如果我們交換中間節點呢?
我們發現,又構成了一條鏈?其實,也不是所有情況都會構成一條鏈,有時也會是交錯的連線。但是無論怎樣,步驟都會增加。
解題思路
- 準備一個數組將儲存進每一個人對應的座位號
- 從開頭開始遍歷,每兩位檢驗一次,如果是情侶則跳過,否則就需要進入換座位的迴圈
- 找到情侶所在的位置,將鄰座和情侶互換
- 換走的鄰居到達了新地方,查詢自己情侶的位置,讓鄰座和自己的情侶換座位
若換到新座位,旁邊恰好是自己的情侶,則終止。
核心程式碼部分
計算座位號
//儲存每個人座位號
for (int i = 0; i < max; i++) {
pos[row[i]] = i;
}
換座位
int lover_site = pos[lover];
//當前旁邊旅客序號及座位號
int beside = row[i + 1];
int beside_site = pos[beside];
//每次配對,讓當前座位的情侶過來,與旁邊的人交換,旁邊的人交換過去後,再次迴圈
//如果交換過去的人旁邊就是自己的情侶,則迴圈結束
while (my_site / 2 != lover_site / 2) {
sum++;
row[beside_site] = lover; //情侶過來
pos[beside] = lover_site;
row[lover_site] = beside; //原座位走開
pos[lover] = beside_site;
//計算走了的旅客現在的情侶,旁邊旅客序號、座位號,並再次迴圈
me = beside;
my_site = pos[me];
if (me % 2 == 0) {
lover = me + 1;
} else {
lover = me - 1;
}
lover_site = pos[lover];
if (my_site % 2 == 0) {
beside = row[my_site + 1];
} else {
beside = row[my_site - 1];
}
beside_site = pos[beside];
}
原始碼
class Solution {
public:
int minSwapsCouples(vector<int>& row) {
int max = row.size();
int pos[max] = {0};
//儲存每個人座位號
for (int i = 0; i < max; i++) {
pos[row[i]] = i;
}
int sum = 0;
int i = 0;
while (i < max) {
//座位上是一對情侶
if (row[i] / 2 == row[i + 1] / 2) {
i = i + 2;
} else {
//當前序號及座位號
int me = row[i];
int my_site = pos[i];
//情侶序號及座位號
int lover;
if (me % 2 == 0) {
lover = me + 1;
} else {
lover = me - 1;
}
int lover_site = pos[lover];
//當前旁邊旅客序號及座位號
int beside = row[i + 1];
int beside_site = pos[beside];
//每次配對,讓當前座位的情侶過來,與旁邊的人交換,旁邊的人交換過去後,再次迴圈
//如果交換過去的人旁邊就是自己的情侶,則迴圈結束
while (my_site / 2 != lover_site / 2) {
sum++;
row[beside_site] = lover; //情侶過來
pos[beside] = lover_site;
row[lover_site] = beside; //原座位走開
pos[lover] = beside_site;
//計算走了的旅客現在的情侶,旁邊旅客序號、座位號,並再次迴圈
me = beside;
my_site = pos[me];
if (me % 2 == 0) {
lover = me + 1;
} else {
lover = me - 1;
}
lover_site = pos[lover];
if (my_site % 2 == 0) {
beside = row[my_site + 1];
} else {
beside = row[my_site - 1];
}
beside_site = pos[beside];
}
i = i + 2;
}
}
return sum;
}
};
執行結果
相關推薦
演算法設計與分析 第三週
題目描述 選題原因 之前兩週做了兩道中等難度的題目,結果還算不錯,因此這次準備選一道困難的題目。篩選了圖演算法,開始選了一道冗餘連線II,完成之後發現題目有一些bug。當選擇的時候,題目要求有多條邊冗餘的時候需要選擇先出現的邊,但是實際測試的時候並不是
演算法設計與分析第三次作業
#leetcode 685.Redundant Connection II In this problem, a rooted tree is a directed graph such that, there is exactly one node (the
演算法設計與分析第八週leetcode
Longest Valid Parentheses Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-
演算法設計與分析第十週Leetcode作業
Edit Distance Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. You hav
短除法求最大公約數(轉自演算法設計與分析第三版)
#include<stdio.h> int main() { /*短除法求最大公約數*/ int i; int j; int a; int b; int t; int c=1; scanf("%d%
演算法設計與分析 第七週 IPO
1.題目描述 2.選題原因 學習了貪心演算法,隨機選擇了一道題目。 3.題目分析及演算法 3.1分析 貪心演算法的本質即是:每一步都選擇當前最好的點,不一定能夠得到全域性最優解,但一定要得到區域性最優解。結合這道題來考慮,按照貪心演算法的思路,在
《演算法設計與分析》第二週作業
《演算法設計與分析》第二週作業 標籤(空格分隔): 課堂作業 《演算法設計與分析》第二週作業 題目概要 思路 嘗試一 嘗試二
《演算法設計與分析》第一週作業
《演算法設計與分析》第一週作業 標籤(空格分隔): 課堂作業 姓名:李** 學號:16340114 題目:Valid Parentheses(https://leetcode.com/problems/valid-parentheses/description/) 題目
演算法設計與分析(三)
53.Course Schedule There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have prerequisites, for
演算法設計與分析第四周練習(圖論)
Network Delay Time 1. 題目 There are N network nodes, labelled 1 to N. Given times, a list of travel times as directed edges times[i
演算法設計與分析第1章 演算法概述
第1章 演算法概述(窮舉演算法) 重要人物:Alan Turing(圖靈機)、Donald Knuth(TEX系統) 演算法:解決問題的一種方法或一個過程 特性:有窮性(Finiteness)、確定性(Definiteness)、可行性(effectivenes
《計算機演算法設計與分析 第4版 (王曉東) 課後答案[1-9章]》pdf版電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《計算機演算法設計與分析 第2版+第3版+第4版 (王曉東) 》原書附答案pdf版電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《演算法設計與分析》第三週作業
《演算法設計與分析》第三週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第三週作業 @[toc] 題目概要 思路 思路一 思路二 具體實
【演算法設計與分析作業題】第十一週:20. Valid Parentheses
題目 C++ solution class Solution { public: bool isValid(string s) { stack<char> cstack; for (int i = 0; i < s.si
《演算法設計與分析》第十一週作業
《演算法設計與分析》第十一週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第十一週作業 @[toc] 題目概要 思路 具體實現 心得 原始碼:
《演算法設計與分析》第十二週作業
《演算法設計與分析》第十二週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第十二週作業 @[toc] 題目概要 思路 具體實現 心得 原始碼:
演算法設計與分析》第十週作業
《演算法設計與分析》第十週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第十週作業 @[toc] 題目概要 思路 具體實現 心得 原始碼:
《演算法設計與分析》第八週作業
《演算法設計與分析》第八週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第八週作業 @[toc] 題目概要 思路 具體實現 心得 原始碼:
《演算法設計與分析》第七週作業
《演算法設計與分析》第七週作業 標籤(空格分隔): 課堂作業 文章目錄 《演算法設計與分析》第七週作業 @[toc] 題目概要 思路 具體實現 心得 原始碼: