838. Push Dominoes

探讨当多米诺骨牌被推向左右两侧时的状态变化,通过实例展示最终形成的稳定状态,并提供两种算法实现。

There are N dominoes in a line, and we place each domino vertically upright.

In the beginning, we simultaneously push some of the dominoes either to the left or to the right.

After each second, each domino that is falling to the left pushes the adjacent domino on the left.

Similarly, the dominoes falling to the right push their adjacent dominoes standing on the right.

When a vertical domino has dominoes falling on it from both sides, it stays still due to the balance of the forces.

For the purposes of this question, we will consider that a falling domino expends no additional force to a falling or already fallen domino.

Given a string "S" representing the initial state. S[i] = 'L', if the i-th domino has been pushed to the left; S[i] = 'R', if the i-th domino has been pushed to the right; S[i] = '.', if the i-th domino has not been pushed.

Return a string representing the final state. 

Example 1:

Input: ".L.R...LR..L.."
Output: "LL.RR.LLRRLL.."
Example 2:

Input: "RR.L"
Output: "RR.L"
Explanation: The first domino expends no additional force on the second domino.
Note:

0 <= N <= 10^5
String dominoes contains only 'L', 'R' and '.'

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/push-dominoes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

暴力破解法:

class Solution {
    public String pushDominoes(String dominoes) {
        if (dominoes.length() <= 1) {
            return dominoes;
        }
         boolean has;
         char[] ans = dominoes.toCharArray();
         while (true) {
             char[] tmp = ans.clone();
             has = false;
             for (int i = 0; i < ans.length; i++) {
                 if (ans[i] == '.') {
                    if (i == 0) {
                        if (ans[i + 1] == 'L') {
                            tmp[i] = 'L';
                            has = true;
                        }
                    } else if (i == ans.length - 1) {
                        if (ans[i - 1] == 'R') {
                            tmp[i] = 'R';
                            has = true;
                        }
                    } else {
                        if (ans[i - 1] == 'R' && ans[i + 1] != 'L') {
                            tmp[i] = 'R';
                            has = true;
                        } else if (ans[i + 1] == 'L' && ans[i - 1] != 'R') {
                            tmp[i] = 'L';
                            has = true;
                        }
                    }
                 }
             }
             ans = tmp.clone();
             if (!has) {
                 break;
             }
         }
         return String.valueOf(ans);
    }
}

分类计算:

1. 如果是两个相同字母之间的.,如L。。。L,或者R。。。R,那么最后都会变成一样的。

2. 如果是方向相反的,如L。。。R,那么不变。

3. 如果是R。。。L,那么就计算中间点的数量,如果是偶数个,那么就对半分,如果是奇数个,那么就中间留一个不变。

class Solution {
    public String pushDominoes(String dominoes) {
        if (dominoes.length() <= 1) {
            return dominoes;
        }
        StringBuilder ans = new StringBuilder();
// 两边先加一个L,R
        dominoes = "L" + dominoes + 'R';
        int index = 0;
        for (int i = 1; i < dominoes.length(); i++) {
            if (dominoes.charAt(i) == '.') {
                continue;
            }
            if (index > 0) {
                ans.append(dominoes.charAt(index));
            }
            if (dominoes.charAt(i) == dominoes.charAt(index)) {
                for (int j = index; j < i - 1; j++) {
                    ans.append(dominoes.charAt(i));
                }
            } else if (dominoes.charAt(index) == 'L' && dominoes.charAt(i) == 'R') {
                for (int j = index; j < i - 1; j++) {
                    ans.append('.');
                }
            } else if (dominoes.charAt(index) == 'R' && dominoes.charAt(i) == 'L') {
                int num = i - index - 1;
                int dot = num % 2;
                for (int j = 0; j < num / 2; j++) {
                    ans.append('R');
                }
                for (int j = 0; j < dot; j++) {
                    ans.append('.');
                }
                for (int j = 0; j < num / 2; j++) {
                    ans.append('L');
                }
            }
            index = i;
        }
        return ans.toString();
    }
}

 

### 问题分析 该问题是要将 `N` 个编号从 1 到 `N` 的多米诺骨牌排成一行。具体的排列规则未明确给出,这里假设要找出某种最优排列(例如按骨牌大小从小到大排列)。 ### 代码实现 ```c #include <stdio.h> #include <stdlib.h> // 比较函数,用于 qsort int compare(const void *a, const void *b) { return (*(int *)a - *(int *)b); } int main() { int N; // 读取多米诺骨牌的数量 scanf("%d", &N); // 动态分配数组来存储每个多米诺骨牌的大小 int *S = (int *)malloc(N * sizeof(int)); if (S == NULL) { fprintf(stderr, "内存分配失败\n"); return 1; } // 读取每个多米诺骨牌的大小 for (int i = 0; i < N; i++) { scanf("%d", &S[i]); } // 使用 qsort 对多米诺骨牌按大小进行排序 qsort(S, N, sizeof(int), compare); // 输出排序后的多米诺骨牌大小 for (int i = 0; i < N; i++) { printf("%d ", S[i]); } printf("\n"); // 释放动态分配的内存 free(S); return 0; } ``` ### 复杂度分析 - **时间复杂度**:排序操作 `qsort` 的时间复杂度为 $O(N log N)$,读取和输出操作的时间复杂度为 $O(N)$,因此总的时间复杂度为 $O(N log N)$。在 2 秒的时间限制内,对于较大的 `N` 也能较快完成。 - **空间复杂度**:只使用了一个大小为 `N` 的数组来存储多米诺骨牌的大小,因此空间复杂度为 $O(N)$。在 1024MiB 的内存限制内,对于一般的 `N` 都能满足要求。 ### 题解说明 此代码首先读取多米诺骨牌的数量 `N`,然后动态分配一个大小为 `N` 的数组来存储每个多米诺骨牌的大小。接着使用 `qsort` 函数对数组进行排序,最后输出排序后的多米诺骨牌大小。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值