Skip to content
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

feat: add solutions to lc problem: No.2197 #2789

Merged
merged 1 commit into from
May 11, 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
138 changes: 138 additions & 0 deletions solution/2100-2199/2197.Replace Non-Coprime Numbers in Array/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,142 @@

## 解法

### 方法一:栈

如果存在三个相邻的数 $x$, $y$, $z$ 可以进行合并,那么我们先合并 $x$ 和 $y$,再合并 $z$ 的结果,与先合并 $y$ 和 $z$,再合并 $x$ 的结果是一样的,结果均为 $\text{LCM}(x, y, z)$。

因此,我们可以总是优先合并左侧相邻的数,再将合并后的结果与右侧相邻的数进行合并。

我们使用一个栈来模拟这个过程,遍历数组,对于每个数,我们将其入栈,然后不断检查栈顶的两个数是否互质,如果不互质,我们将这两个数出栈,然后将它们的最小公倍数入栈,直到栈顶的两个数互质,或者栈中元素小于两个。

最后栈中的元素即为最终结果。

时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n)$。其中 $M$ 为数组中的最大值。

<!-- tabs:start -->

```python
class Solution:
def replaceNonCoprimes(self, nums: List[int]) -> List[int]:
stk = []
for x in nums:
stk.append(x)
while len(stk) > 1:
x, y = stk[-2:]
g = gcd(x, y)
if g == 1:
break
stk.pop()
stk[-1] = x * y // g
return stk
```

```java
class Solution {
public List<Integer> replaceNonCoprimes(int[] nums) {
List<Integer> stk = new ArrayList<>();
for (int x : nums) {
stk.add(x);
while (stk.size() > 1) {
x = stk.get(stk.size() - 1);
int y = stk.get(stk.size() - 2);
int g = gcd(x, y);
if (g == 1) {
break;
}
stk.remove(stk.size() - 1);
stk.set(stk.size() - 1, (int) ((long) x * y / g));
}
}
return stk;
}

private int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
}
```

```cpp
class Solution {
public:
vector<int> replaceNonCoprimes(vector<int>& nums) {
vector<int> stk;
for (int x : nums) {
stk.push_back(x);
while (stk.size() > 1) {
x = stk.back();
int y = stk[stk.size() - 2];
int g = __gcd(x, y);
if (g == 1) {
break;
}
stk.pop_back();
stk.back() = 1LL * x * y / g;
}
}
return stk;
}
};
```

```go
func replaceNonCoprimes(nums []int) []int {
stk := []int{}
for _, x := range nums {
stk = append(stk, x)
for len(stk) > 1 {
x = stk[len(stk)-1]
y := stk[len(stk)-2]
g := gcd(x, y)
if g == 1 {
break
}
stk = stk[:len(stk)-1]
stk[len(stk)-1] = x * y / g
}
}
return stk
}

func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a%b)
}
```

```ts
function replaceNonCoprimes(nums: number[]): number[] {
const gcd = (a: number, b: number): number => {
if (b === 0) {
return a;
}
return gcd(b, a % b);
};
const stk: number[] = [];
for (let x of nums) {
stk.push(x);
while (stk.length > 1) {
x = stk.at(-1)!;
const y = stk.at(-2)!;
const g = gcd(x, y);
if (g === 1) {
break;
}
stk.pop();
stk.pop();
stk.push(((x * y) / g) | 0);
}
}
return stk;
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,142 @@ Note that there are other ways to obtain the same resultant array.

## Solutions

### Solution 1: Stack

If there exist three adjacent numbers $x$, $y$, $z$ that can be merged, then the result of first merging $x$ and $y$, then merging $z$, is the same as the result of first merging $y$ and $z$, then merging $x$. Both results are $\text{LCM}(x, y, z)$.

Therefore, we can always prefer to merge the adjacent numbers on the left, and then merge the result with the adjacent number on the right.

We use a stack to simulate this process. We traverse the array, and for each number, we push it into the stack. Then we continuously check whether the top two numbers of the stack are coprime. If they are not coprime, we pop these two numbers out of the stack, and then push their least common multiple into the stack, until the top two numbers of the stack are coprime, or there are less than two elements in the stack.

The final elements in the stack are the final result.

The time complexity is $O(n \times \log M)$, and the space complexity is $O(n)$. Where $M$ is the maximum value in the array.

<!-- tabs:start -->

```python
class Solution:
def replaceNonCoprimes(self, nums: List[int]) -> List[int]:
stk = []
for x in nums:
stk.append(x)
while len(stk) > 1:
x, y = stk[-2:]
g = gcd(x, y)
if g == 1:
break
stk.pop()
stk[-1] = x * y // g
return stk
```

```java
class Solution {
public List<Integer> replaceNonCoprimes(int[] nums) {
List<Integer> stk = new ArrayList<>();
for (int x : nums) {
stk.add(x);
while (stk.size() > 1) {
x = stk.get(stk.size() - 1);
int y = stk.get(stk.size() - 2);
int g = gcd(x, y);
if (g == 1) {
break;
}
stk.remove(stk.size() - 1);
stk.set(stk.size() - 1, (int) ((long) x * y / g));
}
}
return stk;
}

private int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
}
```

```cpp
class Solution {
public:
vector<int> replaceNonCoprimes(vector<int>& nums) {
vector<int> stk;
for (int x : nums) {
stk.push_back(x);
while (stk.size() > 1) {
x = stk.back();
int y = stk[stk.size() - 2];
int g = __gcd(x, y);
if (g == 1) {
break;
}
stk.pop_back();
stk.back() = 1LL * x * y / g;
}
}
return stk;
}
};
```

```go
func replaceNonCoprimes(nums []int) []int {
stk := []int{}
for _, x := range nums {
stk = append(stk, x)
for len(stk) > 1 {
x = stk[len(stk)-1]
y := stk[len(stk)-2]
g := gcd(x, y)
if g == 1 {
break
}
stk = stk[:len(stk)-1]
stk[len(stk)-1] = x * y / g
}
}
return stk
}

func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a%b)
}
```

```ts
function replaceNonCoprimes(nums: number[]): number[] {
const gcd = (a: number, b: number): number => {
if (b === 0) {
return a;
}
return gcd(b, a % b);
};
const stk: number[] = [];
for (let x of nums) {
stk.push(x);
while (stk.length > 1) {
x = stk.at(-1)!;
const y = stk.at(-2)!;
const g = gcd(x, y);
if (g === 1) {
break;
}
stk.pop();
stk.pop();
stk.push(((x * y) / g) | 0);
}
}
return stk;
}
```

<!-- tabs:end -->

<!-- end -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution {
public:
vector<int> replaceNonCoprimes(vector<int>& nums) {
vector<int> stk;
for (int x : nums) {
stk.push_back(x);
while (stk.size() > 1) {
x = stk.back();
int y = stk[stk.size() - 2];
int g = __gcd(x, y);
if (g == 1) {
break;
}
stk.pop_back();
stk.back() = 1LL * x * y / g;
}
}
return stk;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
func replaceNonCoprimes(nums []int) []int {
stk := []int{}
for _, x := range nums {
stk = append(stk, x)
for len(stk) > 1 {
x = stk[len(stk)-1]
y := stk[len(stk)-2]
g := gcd(x, y)
if g == 1 {
break
}
stk = stk[:len(stk)-1]
stk[len(stk)-1] = x * y / g
}
}
return stk
}

func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a%b)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Solution {
public List<Integer> replaceNonCoprimes(int[] nums) {
List<Integer> stk = new ArrayList<>();
for (int x : nums) {
stk.add(x);
while (stk.size() > 1) {
x = stk.get(stk.size() - 1);
int y = stk.get(stk.size() - 2);
int g = gcd(x, y);
if (g == 1) {
break;
}
stk.remove(stk.size() - 1);
stk.set(stk.size() - 1, (int) ((long) x * y / g));
}
}
return stk;
}

private int gcd(int a, int b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Solution:
def replaceNonCoprimes(self, nums: List[int]) -> List[int]:
stk = []
for x in nums:
stk.append(x)
while len(stk) > 1:
x, y = stk[-2:]
g = gcd(x, y)
if g == 1:
break
stk.pop()
stk[-1] = x * y // g
return stk
Loading
Loading