交换量最小

时间:2018-02-12 18:41:41

标签: algorithm

假设我们得到了1和0的序列(长度为n),例如。 10100100。我们想要重新排列它们,因此1跟随每个00跟随每个1 - 但最后可能会有0个或{ {1}}左边 - 所以我们的序列将成为1。我们假设10101000k 1数量为n-k,因此我们需要0min(n, n-k)10 }(或01)然后剩下的就剩下了。

我们可以做一个操作 - 交换两个选择的元素。我们需要计算将序列重新排列成给定顺序的最小交换量 - 例如我们只需要一次交换(索引45之间,从0索引),以正确地重新排列。对于010101111110101000000,我们需要0互换。

任何想法如何计算?实际上任何复杂性都会受到影响 - 我不知道该怎么做。

2 个答案:

答案 0 :(得分:0)

从您的示例中,我假设您的剩余字符必须出现在字符串的右侧。这意味着之前的字符必须交替。这为最终字符串提供了两种可能的解决方案。在你给出的情况下,这些将是

10101000
01010100

您的整个算法很简单:生成这两个序列(k 0与k 1'交替)并附加n-k个附加内容。将每个与原始数据进行比较,以查看两者中哪一个具有较少数量的移位字符。识别那些对和交换。例如,使用上面的内容:

10100100  original
10101000  candidate
--------
....!!..  two differences, one swap

10100100  original
01010100  candidate
--------
!!!!....  four differences, two swaps

您使用第一个候选人,已确定位置4和5。

答案 1 :(得分:0)

将字符串转换为Ints集合:

DECLARE v_Init_Cnt NUMBER(10):=1;
        v_Tot_Cnt NUMBER(10);

BEGIN

    SELECT COUNT(*) INTO v_Tot_Cnt FROM DIM_DATE;

    WHILE(v_Init_Cnt <= v_Tot_Cnt)
    LOOP

    dbms_output.put_line(v_Init_Cnt);

    VARIABLE v_Id NUMBER(10);
    exec :v_Id:= v_Init_Cnt;

    dbms_output.put_line('var' || v_Id);

    SELECT * FROM FACT_TABLE 
    WHERE WEEK_NAME between (select WEEk_BEGIN FROM DIM_DATE WHERE UNIQUE_ID :=v_Init_Cnt) and (select WEEk_END FROM DIM_DATE WHERE UNIQUE_ID :=v_Init_Cnt) 

    v_Init_Cnt :=  v_Init_Cnt +1;
    END LOOP;

END;  

用索引拉<:p>

("10100100".toList).map (_.toInt-'0')
= List(1, 0, 1, 0, 0, 1, 0, 0)

用模数,找到索引(0,1,2 ...),我们要求的值,(010 ...)a是字符串值,b是可能的,交替值01,c是索引字符串

.zipWithIndex
List((1,0), (0,1), (1,2), (0,3), (0,4), (1,5), (0,6), (0,7))

过滤那些符合期望的人(对于那些相反的顺序,a!= b):

.map {case (a,b)=> (a, b%2, b)}
List((1,0,0), (0,1,1), (1,0,2), (0,1,3), (0,0,4), (1,1,5), (0,0,6), (0,1,7))

通过交替值进行分组以便以后计算:

.filter {case (a,b,c) => a==b }
List((0,0,4), (1,1,5), (0,0,6))

获得长度并计算:

.groupBy {case (a,b,c)=> b}
Map(1 -> List((1,1,5)), 0 -> List((0,0,4), (0,0,6)))

忽略1和0作为标识符,只需计算:

.map {case (a, b) => (a, b.length)}
Map(1 -> 1, 0 -> 2)

由于我们只能在1对应0处执行交换,反之亦然,因此请至少采用以下两者:

.map (i => (i._2))
List(1, 2)

最后,我们不需要c值,它只是用于跟踪,发生了什么。这是没有c的版本,它以1开头,而不是0:

"10100100".toList).map (_.toInt-'0').zipWithIndex.map {case (a,b)=> (a, b%2, b)}.filter {case (a,b,c) => a==b }.groupBy {case (a,b,c)=> b}.map {case (a, b)=> (a, b.length)}.map (i => (i._2)).min
1

这两个值(1,2)中的最小值是解决方案。