演算法導論上應該有這樣的課後題。
歸併的思路,假設f(i,j)表示陣列i到j的逆序對數,那麼有: f(
i,j)
=f(i
,k)+
f(k+
1,j)
,s(i
,j,k
) 其中s(i,j,k)表示逆序對(p
,q),
p∈[i
,k],
q∈[k
+1,j
] 由於歸併排序,我麼得到兩個有序的子陣列l,
r ,那麼當出現逆序對(l
[i],
r[j]
) 時,表示(l
[i]>r[
j]) 也可以得到l[
i..k
]>r[
j],k
為分割點
因此每次只需計算 k−
i+1
在**中,由於歸併時重置了索引,l和r都是從0開始,因此,當出現逆序時(l
[i]>r[
j]) ,先計算l的長度為n1
=q−p
+1,然後減去出現逆序的位置
i ,得到l[
i..q
]的元素的個數。
#include
#include
using
namespace
std;
class solution
}void merge(vector
&a, int p, int q, int r)}}
public:
int inversepairs(vector
data)
};
兩個鍊錶最終匯聚成一股,節點串成y字型。
class solution
return pa;
}};
統計個數就是hash,這裡條件給定了排序陣列,可以不必額外的空間了。用二分找到上下界即可。
由於上下界演算法查詢得到的是開區間,因此要對特殊情況,例如[6,6,6] 6這種情況進行處理。
class solution
return m;
}int upper(const
vector
&a, const
int &k)
return m;
}public:
int getnumberofk(vector
data, int k)
};
廣度優先搜尋和深度優先搜尋都可以做。
廣度優先搜尋,求出層數即可:
class solution }}
public:
int treedepth(treenode* proot)
};
深度優先搜尋是分別遞迴左右子樹,得到左右子樹的深度,然後左右子樹深度選較大者加一,表示加上根節點以後樹的深度。
class solution
public:
int treedepth(treenode* proot)
};
除了出現1次的兩個數字,其他數字出現2次。
相同的數字異或為0,這樣,遍歷陣列兩兩異或將得到乙個結果,這個結果肯定是乙個非0的數,這個數是由陣列唯2出現一次的數得來,找到這個數的二進位制位第乙個不為0的位,將這個陣列劃分為兩個子陣列,就能分別找到這兩個數。
總體來說就四步:
step1:遍歷陣列,兩兩異或得到num1和num2異或的結果tmp
step2:找到tmp的二進位制位中第乙個出現的1 bit位idx
step3:根據這個idx位是否為1將原陣列劃分為兩個子陣列
step4:兩個子陣列分別做step1操作,得到的結果為num1和num2
class solution
//step 3
vector
v1;vector
v2;v1.reserve(data.size());
v2.reserve(data.size());
for (auto i : data)
//step 4
*num1 = 0;
for (auto i : v1)
*num1 ^= i;
*num2 = 0;
for (auto i : v2)
*num2 ^= i;
}};
牛客劍指offer刷題記錄(五)
鍊錶的指標域中,除了有指向下乙個節點的鍊錶以外,還有乙個指向隨機節點的指標。struct listnode 常規做法,空間換時間。先常規的將拷貝的節點用next串起來,遍歷一遍原始鍊錶,然後尾插法即可。在尾插的同時,建立乙個由原始節點指標p到拷貝節點指標c的乙個map。再次遍歷原始指標,如果指標p指...
牛客網劍指offer刷題記錄(更新ing)
1.二維陣列的查詢 class solution else else 索引 1 index new index 3.從尾到頭列印鍊錶 struct listnode class solution while array tmp.size 0 return array result 4.重建二叉樹 d...
劍指 offer 刷題記錄
任誰都躲不過找工作的問題,好希望能多準備一些時間,奈何時間不等人,每天刷幾道題,並且記錄下來吧 def replacespace s write code here num space 0 new s for i in range len s if i num space 1 for i in ra...