avatar
三种颜色的球排列# JobHunting - 待字闺中
j*r
1
有红黄蓝三种颜色的球各N个, 一共3N个球, 次序任意. 只通过操作exchange(i, j),
如何排列成 "红黄蓝红黄蓝红黄蓝..." 的顺序?
解法已有, 但想看看大家的想法.
avatar
a*s
2
// Say you have the following
typedef enum {
red,
yellow,
blue
} Color;
const Color expectedColors[] = {Red, Yellow, Blue};
// The main loop should be something like:
for (int i = 0; i < 3N; i++) {
Color expectedColor = expectedColors[i%3];
if (getColor(i) != expectedColor) {
exchange(i, findNext(i+1, expectedColor));
}
}
int findNext(int start, Color expectedColor) {
while(getColor[start++] != expectedColor);
return start;
}

【在 j*****r 的大作中提到】
: 有红黄蓝三种颜色的球各N个, 一共3N个球, 次序任意. 只通过操作exchange(i, j),
: 如何排列成 "红黄蓝红黄蓝红黄蓝..." 的顺序?
: 解法已有, 但想看看大家的想法.

avatar
j*r
3
这样的话, 相当于选择排序. 复杂度是O(N^2).
这问题有O(N)时间的in-place算法. 我当时想到解法, 但是写代码时加入一些防止越界
的条件判断, 代码显得冗余. 回来整理出代码, 做了测试.
不过我想知道别人在没有见过这问题的情况下, 多长时间能写出正确解答来.

【在 a**********s 的大作中提到】
: // Say you have the following
: typedef enum {
: red,
: yellow,
: blue
: } Color;
: const Color expectedColors[] = {Red, Yellow, Blue};
: // The main loop should be something like:
: for (int i = 0; i < 3N; i++) {
: Color expectedColor = expectedColors[i%3];

avatar
q*m
4
感觉可以先sort 三色旗

【在 j*****r 的大作中提到】
: 有红黄蓝三种颜色的球各N个, 一共3N个球, 次序任意. 只通过操作exchange(i, j),
: 如何排列成 "红黄蓝红黄蓝红黄蓝..." 的顺序?
: 解法已有, 但想看看大家的想法.

avatar
j*r
5
呵呵, 我当时也先想到sort三色旗. 面试官还让我解释了一下三色旗算法.
不过, 先排成RRR..GGG..BBB.., 要再排成RGBRGBRGB..似乎不容易.

【在 q****m 的大作中提到】
: 感觉可以先sort 三色旗
avatar
H*l
6
sort的话in place只用exchange(i,j)有复杂度O(N)的方法么

【在 j*****r 的大作中提到】
: 呵呵, 我当时也先想到sort三色旗. 面试官还让我解释了一下三色旗算法.
: 不过, 先排成RRR..GGG..BBB.., 要再排成RGBRGBRGB..似乎不容易.

avatar
o*g
7
排序和排成题目要求的顺序是一样的
特点是你事先知道每个位置应该是什么颜色的。
跟排数(int)是不一样的,因为拿到一个数你不知道这个数应该在哪儿。
解法是,安排3个指针,分别指向下一个没排好的颜色的地方,开始坐标是0 1 2
然后循环,可以一个颜色一个颜色循环,也可以大家一起循环。
拿到位置的球,如果这个位置就应该放这个球,就看下一个。
如果这个球的位置放的是别的颜色的,就把这个球和这个球该放的地方的球换一下,被
交换的地方的指针往下移。这样这个位置不一定好了,但是被交换的位置肯定好了。下
次循环还看当前位置是什么颜色的球。所以,每次循环都有一个位置颜色是对的。一共
还是需要3N次就好了。

【在 j*****r 的大作中提到】
: 呵呵, 我当时也先想到sort三色旗. 面试官还让我解释了一下三色旗算法.
: 不过, 先排成RRR..GGG..BBB.., 要再排成RGBRGBRGB..似乎不容易.

avatar
j*r
8
算法的确如此.
不知道这个题的出处是哪里.

【在 o***g 的大作中提到】
: 排序和排成题目要求的顺序是一样的
: 特点是你事先知道每个位置应该是什么颜色的。
: 跟排数(int)是不一样的,因为拿到一个数你不知道这个数应该在哪儿。
: 解法是,安排3个指针,分别指向下一个没排好的颜色的地方,开始坐标是0 1 2
: 然后循环,可以一个颜色一个颜色循环,也可以大家一起循环。
: 拿到位置的球,如果这个位置就应该放这个球,就看下一个。
: 如果这个球的位置放的是别的颜色的,就把这个球和这个球该放的地方的球换一下,被
: 交换的地方的指针往下移。这样这个位置不一定好了,但是被交换的位置肯定好了。下
: 次循环还看当前位置是什么颜色的球。所以,每次循环都有一个位置颜色是对的。一共
: 还是需要3N次就好了。

avatar
f*8
9
楼上的算法比较清晰,但是因为EXCHANGE的COST高于SCAN的COST,而这种算法里面
EXCHANGE的次数多了一些,可以做一些优化:
1. 针对三种颜色保存其分别在findNext中返回的位置(start[color]),并将start[
color]+1作为下次搜索的起始点;
2. 在findNext中,如果找到的下一个颜色原本就在其最终应该呆的位置上,就跳过它
,找到一个“放错位置”的该颜色的球。

【在 a**********s 的大作中提到】
: // Say you have the following
: typedef enum {
: red,
: yellow,
: blue
: } Color;
: const Color expectedColors[] = {Red, Yellow, Blue};
: // The main loop should be something like:
: for (int i = 0; i < 3N; i++) {
: Color expectedColor = expectedColors[i%3];

avatar
w*r
10
先排红的, 第k个红的和位置 3k的球交换
拍黄的, 第k个黄的和位置 3k+1的球交换
avatar
j*r
11
algorithmics的算法也可以, 不过是O(N^2).
orang的算法是O(N).

【在 f****8 的大作中提到】
: 楼上的算法比较清晰,但是因为EXCHANGE的COST高于SCAN的COST,而这种算法里面
: EXCHANGE的次数多了一些,可以做一些优化:
: 1. 针对三种颜色保存其分别在findNext中返回的位置(start[color]),并将start[
: color]+1作为下次搜索的起始点;
: 2. 在findNext中,如果找到的下一个颜色原本就在其最终应该呆的位置上,就跳过它
: ,找到一个“放错位置”的该颜色的球。

avatar
j*r
12
差不多. 你知道这个问题的来源吗?

【在 w****r 的大作中提到】
: 先排红的, 第k个红的和位置 3k的球交换
: 拍黄的, 第k个黄的和位置 3k+1的球交换

avatar
o*g
13
不知道出处

【在 j*****r 的大作中提到】
: 算法的确如此.
: 不知道这个题的出处是哪里.

avatar
w*r
14
一起循环似乎不可以,需要一个颜色一个颜色来, 而且只需要排2个颜色就可以了
color = ["B", "R", "R", "R", "B", "B", "G", "G", "G"]
def exchange(color, i, j):
temp = color[i]
color[i] = color[j]
color[j] = temp
def arrange(color, c, pos):
j = pos
for k in range(len(color)):
if ((color[k] == c) & (k%3 != pos)):
while (color[j] == c):
j += 3
exchange(color, k, j)
arrange(color, "R", 0)
arrange(color, "G", 1)

【在 o***g 的大作中提到】
: 排序和排成题目要求的顺序是一样的
: 特点是你事先知道每个位置应该是什么颜色的。
: 跟排数(int)是不一样的,因为拿到一个数你不知道这个数应该在哪儿。
: 解法是,安排3个指针,分别指向下一个没排好的颜色的地方,开始坐标是0 1 2
: 然后循环,可以一个颜色一个颜色循环,也可以大家一起循环。
: 拿到位置的球,如果这个位置就应该放这个球,就看下一个。
: 如果这个球的位置放的是别的颜色的,就把这个球和这个球该放的地方的球换一下,被
: 交换的地方的指针往下移。这样这个位置不一定好了,但是被交换的位置肯定好了。下
: 次循环还看当前位置是什么颜色的球。所以,每次循环都有一个位置颜色是对的。一共
: 还是需要3N次就好了。

avatar
j*r
15
一个颜色一个颜色的确排2个颜色, 剩下的颜色就也对了.
一起循环也可以, 我有代码, 而且用所有全排列测试过. 可能的情况应该是:
N permutations
----------------
1 6
2 90
3 1679
4 34650

【在 w****r 的大作中提到】
: 一起循环似乎不可以,需要一个颜色一个颜色来, 而且只需要排2个颜色就可以了
: color = ["B", "R", "R", "R", "B", "B", "G", "G", "G"]
: def exchange(color, i, j):
: temp = color[i]
: color[i] = color[j]
: color[j] = temp
: def arrange(color, c, pos):
: j = pos
: for k in range(len(color)):
: if ((color[k] == c) & (k%3 != pos)):

avatar
j*u
16
这个跟Leetcode上那道sort color是基本一样的吧..
avatar
j*r
17
mm, 这个满不一样.

【在 j*******u 的大作中提到】
: 这个跟Leetcode上那道sort color是基本一样的吧..
avatar
j*u
18
啊,是呢,尴尬,没好好看题... :)

【在 j*****r 的大作中提到】
: mm, 这个满不一样.
avatar
a*s
19
这个很简单,findNext(i, expectedColor)的调用稍微改变一下:
// The start indices where we should look for a particular color:
int lookupIndices[] = {-1, -1, -1};
// The main loop should be something like:
for (int i = 0; i < 3N; i++) {
Color expectedColor = expectedColors[i%3];
if (getColor(i) != expectedColor) {
int indexOfExpected = findNext(
max(lookupIndices[expectedColor], i+1),
expectedColor);
exchange(i, indexOfExpected);
lookupIndices[expectedColor] = indexOfExpected + 1;
}
}

【在 j*****r 的大作中提到】
: 这样的话, 相当于选择排序. 复杂度是O(N^2).
: 这问题有O(N)时间的in-place算法. 我当时想到解法, 但是写代码时加入一些防止越界
: 的条件判断, 代码显得冗余. 回来整理出代码, 做了测试.
: 不过我想知道别人在没有见过这问题的情况下, 多长时间能写出正确解答来.

avatar
j*r
20
这个没有什么变化吧, 和刚才的算法差不多.
而且findNext()不是必要的, 直接用lookupIndices[expectedColor]就可以.

【在 a**********s 的大作中提到】
: 这个很简单,findNext(i, expectedColor)的调用稍微改变一下:
: // The start indices where we should look for a particular color:
: int lookupIndices[] = {-1, -1, -1};
: // The main loop should be something like:
: for (int i = 0; i < 3N; i++) {
: Color expectedColor = expectedColors[i%3];
: if (getColor(i) != expectedColor) {
: int indexOfExpected = findNext(
: max(lookupIndices[expectedColor], i+1),
: expectedColor);

avatar
m*e
21
先三色旗,再RGBRGB...可以的吧
从RRRRGGGGBBBB变到RGBRGBRGBRGB可以这样:
RRRRGGGGBBBB=>
RGRRRGGGBBBB=>
RGBRRGGGRBBB=>
RGBRRRGGGBBB

【在 j*****r 的大作中提到】
: 呵呵, 我当时也先想到sort三色旗. 面试官还让我解释了一下三色旗算法.
: 不过, 先排成RRR..GGG..BBB.., 要再排成RGBRGBRGB..似乎不容易.

avatar
T*u
22
就是sort吧,三个指针,总指针,红指针,黄指针,总指针不能动红指针黄指针动过的
,从头开始扫,把红得放到k*3,黄的放到1+k*3,扫倒头就好了。
avatar
a*s
23
再想想

【在 j*****r 的大作中提到】
: 这个没有什么变化吧, 和刚才的算法差不多.
: 而且findNext()不是必要的, 直接用lookupIndices[expectedColor]就可以.

avatar
j*r
24
对, 这也可以. 算法代码已经测试通过了.

【在 m******e 的大作中提到】
: 先三色旗,再RGBRGB...可以的吧
: 从RRRRGGGGBBBB变到RGBRGBRGBRGB可以这样:
: RRRRGGGGBBBB=>
: RGRRRGGGBBBB=>
: RGBRRGGGRBBB=>
: RGBRRRGGGBBB

avatar
l*h
25
这个题目的来源就是荷兰旗问题吧。
做荷兰旗swap的时候,保持直接插到从尾巴倒回去走的正确位置.

【在 j*****r 的大作中提到】
: 对, 这也可以. 算法代码已经测试通过了.
相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。