Skip to content

[pull] main from doocs:main #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ tags:

### 方法一:双指针

我们使用两个指针 $a$, $b$ 分别指向两个链表 $headA$, $headB$。
我们使用两个指针 $a$, $b$ 分别指向两个链表 $\textit{headA}$, $\textit{headB}$。

同时遍历链表,当 $a$ 到达链表 $headA$ 的末尾时,重新定位到链表 $headB$ 的头节点;当 $b$ 到达链表 $headB$ 的末尾时,重新定位到链表 $headA$ 的头节点。
同时遍历链表,当 $a$ 到达链表 $\textit{headA}$ 的末尾时,重新定位到链表 $\textit{headB}$ 的头节点;当 $b$ 到达链表 $\textit{headB}$ 的末尾时,重新定位到链表 $\textit{headA}$ 的头节点。

若两指针相遇,所指向的结点就是第一个公共节点。若没相遇,说明两链表无公共节点,此时两个指针都指向 `null`,返回其中一个即可。

时间复杂度 $O(m+n)$,其中 $m$ 和 $n$ 分别是链表 $headA$ 和 $headB$ 的长度。空间复杂度 $O(1)$。
时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别是链表 $\textit{headA}$ 和 $\textit{headB}$ 的长度。空间复杂度 $O(1)$。

<!-- tabs:start -->

Expand Down Expand Up @@ -233,9 +233,8 @@ func getIntersectionNode(headA, headB *ListNode) *ListNode {
*/

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand All @@ -260,9 +259,8 @@ function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): Li
* @return {ListNode}
*/
var getIntersectionNode = function (headA, headB) {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ Explanation: The two lists do not intersect, so return null.

### Solution 1: Two Pointers

We use two pointers $a$ and $b$ to point to two linked lists $headA$ and $headB$ respectively.
We use two pointers $a$ and $b$ to point to the heads of the two linked lists $\textit{headA}$ and $\textit{headB}$, respectively.

We traverse the linked lists simultaneously. When $a$ reaches the end of the linked list $headA$, it is repositioned to the head node of the linked list $headB$. When $b$ reaches the end of the linked list $headB$, it is repositioned to the head node of the linked list $headA$.
Traverse the linked lists simultaneously. When $a$ reaches the end of $\textit{headA}$, redirect it to the head of $\textit{headB}$. Similarly, when $b$ reaches the end of $\textit{headB}$, redirect it to the head of $\textit{headA}$.

If the two pointers meet, the node they point to is the first common node. If they don't meet, it means that the two linked lists have no common nodes. At this time, both pointers point to `null`, and we can return either one.
If the two pointers meet, the node they point to is the first common node. If they do not meet, it means the two linked lists have no common nodes, and both pointers will point to `null`. Return either pointer.

The time complexity is $O(m+n)$, where $m$ and $n$ are the lengths of the linked lists $headA$ and $headB$ respectively. The space complexity is $O(1)$.
The time complexity is $O(m + n)$, where $m$ and $n$ are the lengths of the linked lists $\textit{headA}$ and $\textit{headB}$, respectively. The space complexity is $O(1)$.

<!-- tabs:start -->

Expand Down Expand Up @@ -217,9 +217,8 @@ func getIntersectionNode(headA, headB *ListNode) *ListNode {
*/

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand All @@ -244,9 +243,8 @@ function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): Li
* @return {ListNode}
*/
var getIntersectionNode = function (headA, headB) {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
* @return {ListNode}
*/
var getIntersectionNode = function (headA, headB) {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
*/

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let a = headA;
let b = headB;
while (a != b) {
let [a, b] = [headA, headB];
while (a !== b) {
a = a ? a.next : headB;
b = b ? b.next : headA;
}
Expand Down
138 changes: 98 additions & 40 deletions solution/1300-1399/1366.Rank Teams by Votes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ C 队获得三票「排位第二」,两票「排位第三」。
<strong>输入:</strong>votes = ["WXYZ","XYZW"]
<strong>输出:</strong>"XWYZ"
<strong>解释:</strong>
X 队在并列僵局打破后成为排名第一的团队。X 队和 W 队的「排位第一」票数一样,但是 X 队有一票「排位第二」,而 W 没有获得「排位第二」。
X 队在并列僵局打破后成为排名第一的团队。X 队和 W 队的「排位第一」票数一样,但是 X 队有一票「排位第二」,而 W 没有获得「排位第二」。
</pre>

<p><strong class="example">示例 3:</strong></p>
Expand Down Expand Up @@ -89,7 +89,7 @@ X 队在并列僵局打破后成为排名第一的团队。X 队和 W 队的「

对于每个候选人,我们可以统计他在每个排位上的票数,然后根据不同的排位依次比较票数,票数相同则比较字母。

时间复杂度 $O(n^2 \times \log n)$,空间复杂度 $O(n^2)$。其中 $n$ 为候选人的数量
时间复杂度 $O(n \times m + m^2 \times \log m)$,空间复杂度 $O(m^2)$。其中 $n$ 是 $\textit{votes}$ 的长度,而 $m$ 是候选人的数量,即 $\textit{votes}[0]$ 的长度

<!-- tabs:start -->

Expand All @@ -98,42 +98,41 @@ X 队在并列僵局打破后成为排名第一的团队。X 队和 W 队的「
```python
class Solution:
def rankTeams(self, votes: List[str]) -> str:
n = len(votes[0])
cnt = defaultdict(lambda: [0] * n)
m = len(votes[0])
cnt = defaultdict(lambda: [0] * m)
for vote in votes:
for i, c in enumerate(vote):
cnt[c][i] += 1
return "".join(sorted(votes[0], key=lambda x: (cnt[x], -ord(x)), reverse=True))
return "".join(sorted(cnt, key=lambda c: (cnt[c], -ord(c)), reverse=True))
```

#### Java

```java
class Solution {
public String rankTeams(String[] votes) {
int n = votes[0].length();
int[][] cnt = new int[26][n];
int m = votes[0].length();
int[][] cnt = new int[26][m + 1];
for (var vote : votes) {
for (int i = 0; i < n; ++i) {
cnt[vote.charAt(i) - 'A'][i]++;
for (int i = 0; i < m; ++i) {
++cnt[vote.charAt(i) - 'A'][i];
}
}
Character[] cs = new Character[n];
for (int i = 0; i < n; ++i) {
cs[i] = votes[0].charAt(i);
Character[] s = new Character[m];
for (int i = 0; i < m; ++i) {
s[i] = votes[0].charAt(i);
}
Arrays.sort(cs, (a, b) -> {
Arrays.sort(s, (a, b) -> {
int i = a - 'A', j = b - 'A';
for (int k = 0; k < n; ++k) {
int d = cnt[i][k] - cnt[j][k];
if (d != 0) {
return d > 0 ? -1 : 1;
for (int k = 0; k < m; ++k) {
if (cnt[i][k] != cnt[j][k]) {
return cnt[j][k] - cnt[i][k];
}
}
return a - b;
});
StringBuilder ans = new StringBuilder();
for (char c : cs) {
for (var c : s) {
ans.append(c);
}
return ans.toString();
Expand All @@ -147,25 +146,25 @@ class Solution {
class Solution {
public:
string rankTeams(vector<string>& votes) {
int n = votes[0].size();
int cnt[26][n];
memset(cnt, 0, sizeof cnt);
for (auto& vote : votes) {
for (int i = 0; i < n; ++i) {
cnt[vote[i] - 'A'][i]++;
int m = votes[0].size();
array<array<int, 27>, 26> cnt{};

for (const auto& vote : votes) {
for (int i = 0; i < m; ++i) {
++cnt[vote[i] - 'A'][i];
}
}
string ans = votes[0];
sort(ans.begin(), ans.end(), [&](auto& a, auto& b) {
string s = votes[0];
ranges::sort(s, [&](char a, char b) {
int i = a - 'A', j = b - 'A';
for (int k = 0; k < n; ++k) {
for (int k = 0; k < m; ++k) {
if (cnt[i][k] != cnt[j][k]) {
return cnt[i][k] > cnt[j][k];
}
}
return a < b;
});
return ans;
return string(s.begin(), s.end());
}
};
```
Expand All @@ -174,24 +173,83 @@ public:

```go
func rankTeams(votes []string) string {
cnt := [26][26]int{}
m := len(votes[0])
cnt := [26][27]int{}
for _, vote := range votes {
for i, c := range vote {
cnt[c-'A'][i]++
for i, ch := range vote {
cnt[ch-'A'][i]++
}
}
ans := []byte(votes[0])
sort.Slice(ans, func(i, j int) bool {
cnt1, cnt2 := cnt[ans[i]-'A'], cnt[ans[j]-'A']
for k, a := range cnt1 {
b := cnt2[k]
if a != b {
return a > b
s := []rune(votes[0])
sort.Slice(s, func(i, j int) bool {
a, b := s[i]-'A', s[j]-'A'
for k := 0; k < m; k++ {
if cnt[a][k] != cnt[b][k] {
return cnt[a][k] > cnt[b][k]
}
}
return ans[i] < ans[j]
return s[i] < s[j]
})
return string(ans)
return string(s)
}
```

#### TypeScript

```ts
function rankTeams(votes: string[]): string {
const m = votes[0].length;
const cnt: number[][] = Array.from({ length: 26 }, () => Array(m + 1).fill(0));
for (const vote of votes) {
for (let i = 0; i < m; i++) {
cnt[vote.charCodeAt(i) - 65][i]++;
}
}
const s: string[] = votes[0].split('');
s.sort((a, b) => {
const i = a.charCodeAt(0) - 65;
const j = b.charCodeAt(0) - 65;
for (let k = 0; k < m; k++) {
if (cnt[i][k] !== cnt[j][k]) {
return cnt[j][k] - cnt[i][k];
}
}
return a.localeCompare(b);
});
return s.join('');
}
```

#### Rust

```rust
impl Solution {
pub fn rank_teams(votes: Vec<String>) -> String {
let m = votes[0].len();
let mut cnt = vec![vec![0; m + 1]; 26];

for vote in &votes {
for (i, ch) in vote.chars().enumerate() {
cnt[(ch as u8 - b'A') as usize][i] += 1;
}
}

let mut s: Vec<char> = votes[0].chars().collect();

s.sort_by(|&a, &b| {
let i = (a as u8 - b'A') as usize;
let j = (b as u8 - b'A') as usize;

for k in 0..m {
if cnt[i][k] != cnt[j][k] {
return cnt[j][k].cmp(&cnt[i][k]);
}
}
a.cmp(&b)
});

s.into_iter().collect()
}
}
```

Expand Down
Loading