mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-05 22:59:31 +08:00
Update
This commit is contained in:
@ -214,6 +214,7 @@ class Solution:
|
||||
return result
|
||||
|
||||
```
|
||||
贪心法
|
||||
```python
|
||||
class Solution:
|
||||
def maxSubArray(self, nums):
|
||||
@ -226,8 +227,18 @@ class Solution:
|
||||
if count <= 0: # 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
|
||||
count = 0
|
||||
return result
|
||||
|
||||
|
||||
```
|
||||
动态规划
|
||||
```python
|
||||
class Solution:
|
||||
def maxSubArray(self, nums: List[int]) -> int:
|
||||
dp = [0] * len(nums)
|
||||
dp[0] = nums[0]
|
||||
res = nums[0]
|
||||
for i in range(1, len(nums)):
|
||||
dp[i] = max(dp[i-1] + nums[i], nums[i])
|
||||
res = max(res, dp[i])
|
||||
return res
|
||||
```
|
||||
### Go
|
||||
贪心法
|
||||
|
@ -184,6 +184,16 @@ if __name__ == '__main__':
|
||||
|
||||
### Go:
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func climbStairs(n int, m int) int {
|
||||
dp := make([]int, n+1)
|
||||
dp[0] = 1
|
||||
|
@ -467,9 +467,37 @@ class Solution:
|
||||
num = int(s[start:end+1])
|
||||
return 0 <= num <= 255
|
||||
|
||||
回溯(版本三)
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def restoreIpAddresses(self, s: str) -> List[str]:
|
||||
result = []
|
||||
self.backtracking(s, 0, [], result)
|
||||
return result
|
||||
|
||||
def backtracking(self, s, startIndex, path, result):
|
||||
if startIndex == len(s):
|
||||
result.append('.'.join(path[:]))
|
||||
return
|
||||
|
||||
for i in range(startIndex, min(startIndex+3, len(s))):
|
||||
# 如果 i 往后遍历了,并且当前地址的第一个元素是 0 ,就直接退出
|
||||
if i > startIndex and s[startIndex] == '0':
|
||||
break
|
||||
# 比如 s 长度为 5,当前遍历到 i = 3 这个元素
|
||||
# 因为还没有执行任何操作,所以此时剩下的元素数量就是 5 - 3 = 2 ,即包括当前的 i 本身
|
||||
# path 里面是当前包含的子串,所以有几个元素就表示储存了几个地址
|
||||
# 所以 (4 - len(path)) * 3 表示当前路径至多能存放的元素个数
|
||||
# 4 - len(path) 表示至少要存放的元素个数
|
||||
if (4 - len(path)) * 3 < len(s) - i or 4 - len(path) > len(s) - i:
|
||||
break
|
||||
if i - startIndex == 2:
|
||||
if not int(s[startIndex:i+1]) <= 255:
|
||||
break
|
||||
path.append(s[startIndex:i+1])
|
||||
self.backtracking(s, i+1, path, result)
|
||||
path.pop()
|
||||
```
|
||||
|
||||
### Go
|
||||
|
@ -609,10 +609,13 @@ class Solution:
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
if node:
|
||||
stack.append(node)
|
||||
stack.append(node) # 中
|
||||
stack.append(None)
|
||||
if node.left: stack.append(node.left)
|
||||
if node.right: stack.append(node.right)
|
||||
# 采用数组进行迭代,先将右节点加入,保证左节点能够先出栈
|
||||
if node.right: # 右
|
||||
stack.append(node.right)
|
||||
if node.left: # 左
|
||||
stack.append(node.left)
|
||||
else:
|
||||
real_node = stack.pop()
|
||||
left, right = height_map.get(real_node.left, 0), height_map.get(real_node.right, 0)
|
||||
|
@ -158,7 +158,7 @@ i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i
|
||||
|
||||
如果 curSum<0 说明 区间和1 + 区间和2 < 0, 那么 假设从上图中的位置开始计数curSum不会小于0的话,就是 区间和2>0。
|
||||
|
||||
区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择其实位置了。
|
||||
区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择起始位置了。
|
||||
|
||||
|
||||
**那么局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置**。
|
||||
|
@ -475,7 +475,45 @@ class Solution:
|
||||
words = words[::-1] # 反转单词
|
||||
return ' '.join(words) #列表转换成字符串
|
||||
```
|
||||
(版本四) 将字符串转换为列表后,使用双指针去除空格
|
||||
```python
|
||||
class Solution:
|
||||
def single_reverse(self, s, start: int, end: int):
|
||||
while start < end:
|
||||
s[start], s[end] = s[end], s[start]
|
||||
start += 1
|
||||
end -= 1
|
||||
|
||||
def reverseWords(self, s: str) -> str:
|
||||
result = ""
|
||||
fast = 0
|
||||
# 1. 首先将原字符串反转并且除掉空格, 并且加入到新的字符串当中
|
||||
# 由于Python字符串的不可变性,因此只能转换为列表进行处理
|
||||
s = list(s)
|
||||
s.reverse()
|
||||
while fast < len(s):
|
||||
if s[fast] != " ":
|
||||
if len(result) != 0:
|
||||
result += " "
|
||||
while s[fast] != " " and fast < len(s):
|
||||
result += s[fast]
|
||||
fast += 1
|
||||
else:
|
||||
fast += 1
|
||||
# 2.其次将每个单词进行翻转操作
|
||||
slow = 0
|
||||
fast = 0
|
||||
result = list(result)
|
||||
while fast <= len(result):
|
||||
if fast == len(result) or result[fast] == " ":
|
||||
self.single_reverse(result, slow, fast - 1)
|
||||
slow = fast + 1
|
||||
fast += 1
|
||||
else:
|
||||
fast += 1
|
||||
|
||||
return "".join(result)
|
||||
```
|
||||
### Go:
|
||||
|
||||
版本一:
|
||||
|
@ -454,7 +454,11 @@ impl Solution {
|
||||
p: Option<Rc<RefCell<TreeNode>>>,
|
||||
q: Option<Rc<RefCell<TreeNode>>>,
|
||||
) -> Option<Rc<RefCell<TreeNode>>> {
|
||||
if root == p || root == q || root.is_none() {
|
||||
if root.is_none() {
|
||||
return root;
|
||||
}
|
||||
if Rc::ptr_eq(root.as_ref().unwrap(), p.as_ref().unwrap())
|
||||
|| Rc::ptr_eq(root.as_ref().unwrap(), q.as_ref().unwrap()) {
|
||||
return root;
|
||||
}
|
||||
let left = Self::lowest_common_ancestor(
|
||||
|
@ -337,6 +337,29 @@ pub fn length_of_lis(nums: Vec<i32>) -> i32 {
|
||||
}
|
||||
```
|
||||
|
||||
### Cangjie:
|
||||
|
||||
```cangjie
|
||||
func lengthOfLIS(nums: Array<Int64>): Int64 {
|
||||
let n = nums.size
|
||||
if (n <= 1) {
|
||||
return n
|
||||
}
|
||||
|
||||
let dp = Array(n, item: 1)
|
||||
var res = 0
|
||||
for (i in 1..n) {
|
||||
for (j in 0..i) {
|
||||
if (nums[i] > nums[j]) {
|
||||
dp[i] = max(dp[i], dp[j] + 1)
|
||||
}
|
||||
}
|
||||
res = max(dp[i], res)
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
|
@ -243,6 +243,29 @@ class Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
贪心
|
||||
```Java
|
||||
class Solution {
|
||||
public int integerBreak(int n) {
|
||||
// with 贪心
|
||||
// 通过数学原理拆出更多的3乘积越大,则
|
||||
/**
|
||||
@Param: an int, the integer we need to break.
|
||||
@Return: an int, the maximum integer after breaking
|
||||
@Method: Using math principle to solve this problem
|
||||
@Time complexity: O(1)
|
||||
**/
|
||||
if(n == 2) return 1;
|
||||
if(n == 3) return 2;
|
||||
int result = 1;
|
||||
while(n > 4) {
|
||||
n-=3;
|
||||
result *=3;
|
||||
}
|
||||
return result*n;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
动态规划(版本一)
|
||||
|
@ -177,7 +177,7 @@ KMP算法中next数组为什么遇到字符不匹配的时候可以找到上一
|
||||
|
||||

|
||||
|
||||
这里有录友就想:如果字符串s 是有是有最小重复子串p组成,最长相等前后缀就不能更长一些? 例如这样:
|
||||
这里有录友就想:如果字符串s 是由最小重复子串p组成,最长相等前后缀就不能更长一些? 例如这样:
|
||||
|
||||

|
||||
|
||||
@ -884,3 +884,4 @@ public int[] GetNext(string s)
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -706,6 +706,57 @@ class Solution:
|
||||
```
|
||||
|
||||
### Go
|
||||
二维dp
|
||||
```go
|
||||
func findTargetSumWays(nums []int, target int) int {
|
||||
sum := 0
|
||||
for _, v := range nums {
|
||||
sum += v
|
||||
}
|
||||
if math.Abs(float64(target)) > float64(sum) {
|
||||
return 0 // 此时没有方案
|
||||
}
|
||||
if (target + sum) % 2 == 1 {
|
||||
return 0 // 此时没有方案
|
||||
}
|
||||
bagSize := (target + sum) / 2
|
||||
|
||||
dp := make([][]int, len(nums))
|
||||
for i := range dp {
|
||||
dp[i] = make([]int, bagSize + 1)
|
||||
}
|
||||
|
||||
// 初始化最上行
|
||||
if nums[0] <= bagSize {
|
||||
dp[0][nums[0]] = 1
|
||||
}
|
||||
|
||||
// 初始化最左列,最左列其他数值在递推公式中就完成了赋值
|
||||
dp[0][0] = 1
|
||||
|
||||
var numZero float64
|
||||
for i := range nums {
|
||||
if nums[i] == 0 {
|
||||
numZero++
|
||||
}
|
||||
dp[i][0] = int(math.Pow(2, numZero))
|
||||
}
|
||||
|
||||
// 以下遍历顺序行列可以颠倒
|
||||
for i := 1; i < len(nums); i++ { // 行,遍历物品
|
||||
for j := 0; j <= bagSize; j++ { // 列,遍历背包
|
||||
if nums[i] > j {
|
||||
dp[i][j] = dp[i-1][j]
|
||||
} else {
|
||||
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(nums)-1][bagSize]
|
||||
}
|
||||
```
|
||||
|
||||
一维dp
|
||||
```go
|
||||
func findTargetSumWays(nums []int, target int) int {
|
||||
sum := 0
|
||||
|
@ -288,6 +288,7 @@ class Solution:
|
||||
|
||||
### Go:
|
||||
|
||||
一维dp
|
||||
```go
|
||||
func change(amount int, coins []int) int {
|
||||
// 定义dp数组
|
||||
@ -306,6 +307,29 @@ func change(amount int, coins []int) int {
|
||||
return dp[amount]
|
||||
}
|
||||
```
|
||||
二维dp
|
||||
```go
|
||||
func change(amount int, coins []int) int {
|
||||
dp := make([][]int, len(coins))
|
||||
for i := range dp {
|
||||
dp[i] = make([]int, amount + 1)
|
||||
dp[i][0] = 1
|
||||
}
|
||||
for j := coins[0]; j <= amount; j++ {
|
||||
dp[0][j] += dp[0][j-coins[0]]
|
||||
}
|
||||
for i := 1; i < len(coins); i++ {
|
||||
for j := 1; j <= amount; j++ {
|
||||
if j < coins[i] {
|
||||
dp[i][j] = dp[i-1][j]
|
||||
} else {
|
||||
dp[i][j] = dp[i][j-coins[i]] + dp[i-1][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(coins)-1][amount]
|
||||
}
|
||||
```
|
||||
|
||||
### Rust:
|
||||
|
||||
|
@ -492,6 +492,25 @@ int findLengthOfLCIS(int* nums, int numsSize) {
|
||||
}
|
||||
```
|
||||
|
||||
### Cangjie
|
||||
|
||||
```cangjie
|
||||
func findLengthOfLCIS(nums: Array<Int64>): Int64 {
|
||||
let n = nums.size
|
||||
if (n <= 1) {
|
||||
return n
|
||||
}
|
||||
let dp = Array(n, repeat: 1)
|
||||
var res = 0
|
||||
for (i in 1..n) {
|
||||
if (nums[i] > nums[i - 1]) {
|
||||
dp[i] = dp[i - 1] + 1
|
||||
}
|
||||
res = max(res, dp[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -581,6 +581,25 @@ int findLength(int* nums1, int nums1Size, int* nums2, int nums2Size) {
|
||||
}
|
||||
```
|
||||
|
||||
### Cangjie
|
||||
|
||||
```cangjie
|
||||
func findLength(nums1: Array<Int64>, nums2: Array<Int64>): Int64 {
|
||||
let n = nums1.size
|
||||
let m = nums2.size
|
||||
let dp = Array(n + 1, {_ => Array(m + 1, item: 0)})
|
||||
var res = 0
|
||||
for (i in 1..=n) {
|
||||
for (j in 1..=m) {
|
||||
if (nums1[i - 1] == nums2[j - 1]) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1
|
||||
}
|
||||
res = max(res, dp[i][j])
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<p align="center">
|
||||
|
@ -399,6 +399,25 @@ int longestCommonSubsequence(char* text1, char* text2) {
|
||||
}
|
||||
```
|
||||
|
||||
### Cangjie
|
||||
|
||||
```cangjie
|
||||
func longestCommonSubsequence(text1: String, text2: String): Int64 {
|
||||
let n = text1.size
|
||||
let m = text2.size
|
||||
let dp = Array(n + 1, {_ => Array(m + 1, repeat: 0)})
|
||||
for (i in 1..=n) {
|
||||
for (j in 1..=m) {
|
||||
if (text1[i - 1] == text2[j - 1]) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1
|
||||
} else {
|
||||
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[n][m]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<p align="center">
|
||||
|
@ -549,6 +549,62 @@ if __name__ == "__main__":
|
||||
|
||||
### Javascript
|
||||
|
||||
```js
|
||||
function kruskal(v, edges) {
|
||||
const father = Array.from({ length: v + 1 }, (_, i) => i)
|
||||
|
||||
function find(u){
|
||||
if (u === father[u]) {
|
||||
return u
|
||||
} else {
|
||||
father[u] = find(father[u])
|
||||
return father[u]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function isSame(u, v) {
|
||||
let s = find(u)
|
||||
let t = find(v)
|
||||
return s === t
|
||||
}
|
||||
|
||||
function join(u, v) {
|
||||
let s = find(u)
|
||||
let t = find(v)
|
||||
if (s !== t) {
|
||||
father[s] = t
|
||||
}
|
||||
}
|
||||
|
||||
edges.sort((a, b) => a[2] - b[2])
|
||||
let result = 0
|
||||
for (const [v1, v2, w] of edges) {
|
||||
if (!isSame(v1, v2)) {
|
||||
result += w
|
||||
join(v1 ,v2)
|
||||
}
|
||||
}
|
||||
console.log(result)
|
||||
}
|
||||
|
||||
|
||||
async function main() {
|
||||
const rl = require('readline').createInterface({ input: process.stdin })
|
||||
const iter = rl[Symbol.asyncIterator]()
|
||||
const readline = async () => (await iter.next()).value
|
||||
const [v, e] = (await readline()).split(" ").map(Number)
|
||||
const edges = []
|
||||
for (let i = 0 ; i < e ; i++) {
|
||||
edges.push((await readline()).split(" ").map(Number))
|
||||
}
|
||||
kruskal(v, edges)
|
||||
}
|
||||
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
### PhP
|
||||
|
@ -693,6 +693,55 @@ if __name__ == "__main__":
|
||||
### Rust
|
||||
|
||||
### Javascript
|
||||
```js
|
||||
function prim(v, edges) {
|
||||
const grid = Array.from({ length: v + 1 }, () => new Array(v + 1).fill(10001)); // Fixed grid initialization
|
||||
const minDist = new Array(v + 1).fill(10001)
|
||||
const isInTree = new Array(v + 1).fill(false)
|
||||
// 建構鄰接矩陣
|
||||
for(const [v1, v2, w] of edges) {
|
||||
grid[v1][v2] = w
|
||||
grid[v2][v1] = w
|
||||
}
|
||||
// prim 演算法
|
||||
for (let i = 1 ; i < v ; i++) {
|
||||
let cur = -1
|
||||
let tempMinDist = Number.MAX_VALUE
|
||||
// 1. 尋找距離生成樹最近的節點
|
||||
for (let j = 1 ; j < v + 1 ; j++) {
|
||||
if (!isInTree[j] && minDist[j] < tempMinDist) {
|
||||
tempMinDist = minDist[j]
|
||||
cur = j
|
||||
}
|
||||
}
|
||||
// 2. 將節點放入生成樹
|
||||
isInTree[cur] = true
|
||||
// 3. 更新非生成樹節點與生成樹的最短距離
|
||||
for (let j = 1 ; j < v + 1 ; j++) {
|
||||
if (!isInTree[j] && grid[cur][j] < minDist[j]) {
|
||||
minDist[j] = grid[cur][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(minDist.slice(2).reduce((acc, cur) => acc + cur, 0))
|
||||
}
|
||||
|
||||
|
||||
async function main() {
|
||||
const rl = require('readline').createInterface({ input: process.stdin })
|
||||
const iter = rl[Symbol.asyncIterator]()
|
||||
const readline = async () => (await iter.next()).value
|
||||
const [v, e] = (await readline()).split(" ").map(Number)
|
||||
const edges = []
|
||||
for (let i = 0 ; i < e ; i++) {
|
||||
edges.push((await readline()).split(" ").map(Number))
|
||||
}
|
||||
prim(v, edges)
|
||||
}
|
||||
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
|
@ -480,7 +480,84 @@ const bfs = (graph, visited, x, y) => {
|
||||
})()
|
||||
```
|
||||
|
||||
```javascript
|
||||
|
||||
// 深搜版
|
||||
|
||||
const r1 = require('readline').createInterface({ input: process.stdin });
|
||||
// 创建readline接口
|
||||
let iter = r1[Symbol.asyncIterator]();
|
||||
// 创建异步迭代器
|
||||
const readline = async () => (await iter.next()).value;
|
||||
|
||||
let graph // 地图
|
||||
let N, M // 地图大小
|
||||
let visited // 访问过的节点
|
||||
let result = 0 // 最大岛屿面积
|
||||
let count = 0 // 岛屿内节点数
|
||||
const dir = [[0, 1], [1, 0], [0, -1], [-1, 0]] //方向
|
||||
|
||||
// 读取输入,初始化地图
|
||||
const initGraph = async () => {
|
||||
let line = await readline();
|
||||
[N, M] = line.split(' ').map(Number);
|
||||
graph = new Array(N).fill(0).map(() => new Array(M).fill(0))
|
||||
visited = new Array(N).fill(false).map(() => new Array(M).fill(false))
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
line = await readline()
|
||||
line = line.split(' ').map(Number)
|
||||
for (let j = 0; j < M; j++) {
|
||||
graph[i][j] = line[j]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 从(x, y)开始深度优先遍历
|
||||
* @param {*} graph 地图
|
||||
* @param {*} visited 访问过的节点
|
||||
* @param {*} x 开始搜索节点的下标
|
||||
* @param {*} y 开始搜索节点的下标
|
||||
* @return {*}
|
||||
*/
|
||||
const dfs = (graph, visited, x, y) => {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let nextx = x + dir[i][0]
|
||||
let nexty = y + dir[i][1]
|
||||
if(nextx < 0 || nextx >= N || nexty < 0 || nexty >= M) continue
|
||||
if(!visited[nextx][nexty] && graph[nextx][nexty] === 1){
|
||||
count++
|
||||
visited[nextx][nexty] = true
|
||||
dfs(graph, visited, nextx, nexty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
||||
// 读取输入,初始化地图
|
||||
await initGraph()
|
||||
|
||||
// 统计最大岛屿面积
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let j = 0; j < M; j++) {
|
||||
if (!visited[i][j] && graph[i][j] === 1) { //遇到没有访问过的陆地
|
||||
// 重新计算面积
|
||||
count = 1
|
||||
visited[i][j] = true
|
||||
|
||||
// 深度优先遍历,统计岛屿内节点数,并将岛屿标记为已访问
|
||||
dfs(graph, visited, i, j)
|
||||
|
||||
// 更新最大岛屿面积
|
||||
result = Math.max(result, count)
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(result);
|
||||
})()
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
|
@ -307,6 +307,71 @@ for i in range(n):
|
||||
|
||||
print(count)
|
||||
```
|
||||
|
||||
```python
|
||||
direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
|
||||
result = 0
|
||||
|
||||
# 深度搜尋
|
||||
def dfs(grid, y, x):
|
||||
grid[y][x] = 0
|
||||
global result
|
||||
result += 1
|
||||
|
||||
for i, j in direction:
|
||||
next_x = x + j
|
||||
next_y = y + i
|
||||
if (next_x < 0 or next_y < 0 or
|
||||
next_x >= len(grid[0]) or next_y >= len(grid)
|
||||
):
|
||||
continue
|
||||
if grid[next_y][next_x] == 1 and not visited[next_y][next_x]:
|
||||
visited[next_y][next_x] = True
|
||||
dfs(grid, next_y, next_x)
|
||||
|
||||
|
||||
# 讀取輸入值
|
||||
n, m = map(int, input().split())
|
||||
grid = []
|
||||
visited = [[False] * m for _ in range(n)]
|
||||
|
||||
for i in range(n):
|
||||
grid.append(list(map(int, input().split())))
|
||||
|
||||
# 處理邊界
|
||||
for j in range(m):
|
||||
# 上邊界
|
||||
if grid[0][j] == 1 and not visited[0][j]:
|
||||
visited[0][j] = True
|
||||
dfs(grid, 0, j)
|
||||
# 下邊界
|
||||
if grid[n - 1][j] == 1 and not visited[n - 1][j]:
|
||||
visited[n - 1][j] = True
|
||||
dfs(grid, n - 1, j)
|
||||
|
||||
for i in range(n):
|
||||
# 左邊界
|
||||
if grid[i][0] == 1 and not visited[i][0]:
|
||||
visited[i][0] = True
|
||||
dfs(grid, i, 0)
|
||||
# 右邊界
|
||||
if grid[i][m - 1] == 1 and not visited[i][m - 1]:
|
||||
visited[i][m - 1] = True
|
||||
dfs(grid, i, m - 1)
|
||||
|
||||
# 計算孤島總面積
|
||||
result = 0 # 初始化,避免使用到處理邊界時所產生的累加值
|
||||
|
||||
for i in range(n):
|
||||
for j in range(m):
|
||||
if grid[i][j] == 1 and not visited[i][j]:
|
||||
visited[i][j] = True
|
||||
dfs(grid, i, j)
|
||||
|
||||
# 輸出孤島的總面積
|
||||
print(result)
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
``` go
|
||||
|
@ -178,6 +178,45 @@ int main() {
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
father = list()
|
||||
|
||||
def find(u):
|
||||
if u == father[u]:
|
||||
return u
|
||||
else:
|
||||
father[u] = find(father[u])
|
||||
return father[u]
|
||||
|
||||
def is_same(u, v):
|
||||
u = find(u)
|
||||
v = find(v)
|
||||
return u == v
|
||||
|
||||
def join(u, v):
|
||||
u = find(u)
|
||||
v = find(v)
|
||||
if u != v:
|
||||
father[u] = v
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 輸入
|
||||
n = int(input())
|
||||
for i in range(n + 1):
|
||||
father.append(i)
|
||||
# 尋找冗余邊
|
||||
result = None
|
||||
for i in range(n):
|
||||
s, t = map(int, input().split())
|
||||
if is_same(s, t):
|
||||
result = str(s) + ' ' + str(t)
|
||||
else:
|
||||
join(s, t)
|
||||
|
||||
# 輸出
|
||||
print(result)
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
### Rust
|
||||
|
@ -250,9 +250,193 @@ int main() {
|
||||
## 其他语言版本
|
||||
|
||||
### Java
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
static int n;
|
||||
static int[] father = new int[1001]; // 并查集数组
|
||||
|
||||
// 并查集初始化
|
||||
public static void init() {
|
||||
for (int i = 1; i <= n; ++i) {
|
||||
father[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 并查集里寻根的过程
|
||||
public static int find(int u) {
|
||||
if (u == father[u]) return u;
|
||||
return father[u] = find(father[u]); // 路径压缩
|
||||
}
|
||||
|
||||
// 将 v->u 这条边加入并查集
|
||||
public static void join(int u, int v) {
|
||||
u = find(u);
|
||||
v = find(v);
|
||||
if (u != v) {
|
||||
father[v] = u; // 合并两棵树
|
||||
}
|
||||
}
|
||||
|
||||
// 判断 u 和 v 是否有同一个根
|
||||
public static boolean same(int u, int v) {
|
||||
return find(u) == find(v);
|
||||
}
|
||||
|
||||
// 在有向图里找到删除的那条边,使其变成树
|
||||
public static void getRemoveEdge(List<int[]> edges) {
|
||||
init(); // 初始化并查集
|
||||
for (int i = 0; i < n; i++) { // 遍历所有的边
|
||||
if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,就是要删除的边
|
||||
System.out.println(edges.get(i)[0] + " " + edges.get(i)[1]);
|
||||
return;
|
||||
} else {
|
||||
join(edges.get(i)[0], edges.get(i)[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删一条边之后判断是不是树
|
||||
public static boolean isTreeAfterRemoveEdge(List<int[]> edges, int deleteEdge) {
|
||||
init(); // 初始化并查集
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (i == deleteEdge) continue;
|
||||
if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,一定不是树
|
||||
return false;
|
||||
}
|
||||
join(edges.get(i)[0], edges.get(i)[1]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
List<int[]> edges = new ArrayList<>(); // 存储所有的边
|
||||
|
||||
n = sc.nextInt(); // 顶点数
|
||||
int[] inDegree = new int[n + 1]; // 记录每个节点的入度
|
||||
for (int i = 0; i < n; i++) {
|
||||
int s = sc.nextInt(); // 边的起点
|
||||
int t = sc.nextInt(); // 边的终点
|
||||
inDegree[t]++;
|
||||
edges.add(new int[]{s, t}); // 将边加入列表
|
||||
}
|
||||
|
||||
List<Integer> vec = new ArrayList<>(); // 记录入度为2的边(如果有的话就两条边)
|
||||
// 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
if (inDegree[edges.get(i)[1]] == 2) {
|
||||
vec.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
// 情况一、情况二
|
||||
if (vec.size() > 0) {
|
||||
// vec里的边已经按照倒叙放的,所以优先删 vec.get(0) 这条边
|
||||
if (isTreeAfterRemoveEdge(edges, vec.get(0))) {
|
||||
System.out.println(edges.get(vec.get(0))[0] + " " + edges.get(vec.get(0))[1]);
|
||||
} else {
|
||||
System.out.println(edges.get(vec.get(1))[0] + " " + edges.get(vec.get(1))[1]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理情况三:明确没有入度为2的情况,一定有有向环,找到构成环的边返回即可
|
||||
getRemoveEdge(edges);
|
||||
}
|
||||
}
|
||||
```
|
||||
### Python
|
||||
|
||||
```python
|
||||
from collections import defaultdict
|
||||
|
||||
father = list()
|
||||
|
||||
|
||||
def find(u):
|
||||
if u == father[u]:
|
||||
return u
|
||||
else:
|
||||
father[u] = find(father[u])
|
||||
return father[u]
|
||||
|
||||
|
||||
def is_same(u, v):
|
||||
u = find(u)
|
||||
v = find(v)
|
||||
return u == v
|
||||
|
||||
|
||||
def join(u, v):
|
||||
u = find(u)
|
||||
v = find(v)
|
||||
if u != v:
|
||||
father[u] = v
|
||||
|
||||
|
||||
def is_tree_after_remove_edge(edges, edge, n):
|
||||
# 初始化并查集
|
||||
global father
|
||||
father = [i for i in range(n + 1)]
|
||||
|
||||
for i in range(len(edges)):
|
||||
if i == edge:
|
||||
continue
|
||||
s, t = edges[i]
|
||||
if is_same(s, t): # 成環,即不是有向樹
|
||||
return False
|
||||
else: # 將s,t放入集合中
|
||||
join(s, t)
|
||||
return True
|
||||
|
||||
|
||||
def get_remove_edge(edges):
|
||||
# 初始化并查集
|
||||
global father
|
||||
father = [i for i in range(n + 1)]
|
||||
|
||||
for s, t in edges:
|
||||
if is_same(s, t):
|
||||
print(s, t)
|
||||
return
|
||||
else:
|
||||
join(s, t)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 輸入
|
||||
n = int(input())
|
||||
edges = list()
|
||||
in_degree = defaultdict(int)
|
||||
|
||||
for i in range(n):
|
||||
s, t = map(int, input().split())
|
||||
in_degree[t] += 1
|
||||
edges.append([s, t])
|
||||
|
||||
# 尋找入度為2的邊,並紀錄其下標(index)
|
||||
vec = list()
|
||||
for i in range(n - 1, -1, -1):
|
||||
if in_degree[edges[i][1]] == 2:
|
||||
vec.append(i)
|
||||
|
||||
# 輸出
|
||||
if len(vec) > 0:
|
||||
# 情況一:刪除輸出順序靠後的邊
|
||||
if is_tree_after_remove_edge(edges, vec[0], n):
|
||||
print(edges[vec[0]][0], edges[vec[0]][1])
|
||||
# 情況二:只能刪除特定的邊
|
||||
else:
|
||||
print(edges[vec[1]][0], edges[vec[1]][1])
|
||||
else:
|
||||
# 情況三: 原圖有環
|
||||
get_remove_edge(edges)
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
### Rust
|
||||
|
Reference in New Issue
Block a user