A,B序列调换问题

nandizhu 2009-08-11 04:57:49
有两段整数序列A,B

能做的操作只有change(i,j)意思是对换i,j位置上的整数,
现在问B序列需要最少好多次change操作才能变成A序列

如果不能变成A序列则输出-1
...全文
365 点赞 收藏 16
写回复
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
bigbug9002 2009-08-14
前几天还做一个类似的题:
public class Sorter{
private HashMap<Item,Integer> originalList=new HashMap<Item,Integer>();
//在构造方法中把myList中的数据的序号用HashMap记录下来.
//
Sorter(List<Item> myList){
for(int i=0;i<myList.size();i++){
originalList.put(myList.get(i),i);
}
}
//用自己定义的comparator对另一个myList排序,java自己做好sort方法应该采用的是归并排序。
//交换元素最少的应该是快排吧。
//
public void sort(List<Item> myList){
Collections.sort(myList,new comparator());
}

//自己定义的比较器,用两个数据的序号来决定他们的次序。,
//
public class comparator implements Comparator<Item>{
public int compare(Item i1,Item i2){
return originalList.get(i1)-originalList.get(i2);
}
public boolean equals(Object o){
return false;
}
}
}
回复
gumbour 2009-08-14
交换次数最多为 n,
for (i=0;i<n;i++)
{
找到j使,a[i]=b[j];
交换b[i],b[j];

如果某个I找不到对应的J,则 return -1;
}



楼主只说了要最少交换次数,不要求最少比较次数,所以 O(nlogn)可能是算法复杂度,但肯定不是交换的复杂度。

回复
tanwan 2009-08-13
先找出序列,然后在不对称的放进一个队列里然后每次找的时候有不对称的都与队列里去判断,对称上的就++然后在判断2个是否全部对称,全部对称就过,如果有不对称的就继续往里面添加
回复
linren 2009-08-12
(上接7楼)

【说明】
因为数组下标从0位开始
所以“change 1,8”表示的实际上是把B中的第2个数(1位)和第9个数(8位)进行交换……

6楼的算法得到的或许一定是最优解
但是目前还不知道怎样来证明这点……
同时也找不到一个反例来证明这样得到的不是最优解……
回复
showjim 2009-08-12
[Quote=引用 2 楼 paradin 的回复:]
mark
找圈圈。
[/Quote]
找尽可能多的环
回复
AppZ 2009-08-12
m
回复
fire_woods 2009-08-12
先排序.
回复
fxg0110 2009-08-12
想来想去还是只有找圈圈能效率高点
找环的条件:
1.串环时A中元素连对应位置B中元素,B中元素连A中对应数值A中元素
2.每个元素仅可被串一次
3.若A、B元素个数不一样,或有元素没有被串(即有元素不能构成环)

if(A.size!=B.size||有元素不能构成环) return -1;
return A.size-总环数


本来想写写代码的,但有事就只好先谢谢思路了,哈哈
回复
fxg0110 2009-08-12
好像只是要返回次数而已吧
回复
linren 2009-08-11
(上接6楼)

【程序】
#include <stdio.h>
#include <stdlib.h>
/**只用修改这里*******************************/
#define ASIZE 10
int a[10]={1,2,3,4,5,6,7,8,9,10};
int b[10]={1,5,10,3,4,6,8,7,2,9};
/*******************************只用修改这里**/

struct node{
int a,b;
};

int fun(int *a,int *b,int len){
int i,j,z,c=0,t=0,r=0,tmp;
char *ruler;
struct node* note;
int *chose;
int *save;

printf("A\t");
for(i=0;i<len;i++) printf("%d, ",a[i]);printf("\n");

/* 保存B的值 */
save=(int*)malloc(sizeof(int)*len);
printf("B\t");
for(i=0;i<len;i++){
printf("%d, ",b[i]);save[i]=b[i];
}printf("\n");

/* 创建标尺 */
ruler=(char*)malloc(sizeof(char)*len);
for(i=0;i<len;i++){
if(a[i]==b[i]) ruler[i]=1;
else{
ruler[i]=0;c++;
}
}

/* 创建记录本 */
note=(struct node*)malloc(sizeof(struct node)*c);
chose=(int*)malloc(sizeof(int)*c);


for(i=0;i<len;i++){
if(ruler[i]==1) continue;
r=0;
for(j=i+1;j<len;j++){
if(ruler[j]==1) continue;
if(a[i]==b[j]) chose[r++]=j;
}

/* B不能变成A */
if(r==0){
free(ruler);free(note);free(chose);free(save);return -1;
}

/* 优选 */
for(z=0;z<r;z++){
if(a[chose[z]]==b[i]){
note[t].a=i;note[t].b=chose[z];t++;
ruler[i]=1;ruler[chose[z]]=1;
tmp=b[i];b[i]=b[chose[z]];b[chose[z]]=tmp;c=c-2;
}
}
if(ruler[i]==1) continue;

/* 随选 */
note[t].a=i;note[t].b=chose[0];t++;
ruler[i]=1;
tmp=b[i];b[i]=b[chose[0]];b[chose[0]]=tmp;c=c-1;
}
for(i=0;i<t;i++){
printf("change %d,%d\n",note[i].a,note[i].b);
printf("B\t");
tmp=save[note[i].a];save[note[i].a]=save[note[i].b];save[note[i].b]=tmp;
for(j=0;j<len;j++) printf("%d, ",save[j]);printf("\n");
}

free(ruler);free(note);free(chose);free(save);return 0;
}

int main(){
if(fun(a,b,ASIZE)==-1) printf("can not change B to A!\n");
return 0;
}

【运行结果】
A 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
B 1, 5, 10, 3, 4, 6, 8, 7, 2, 9,
change 1,8
B 1, 2, 10, 3, 4, 6, 8, 7, 5, 9,
change 2,3
B 1, 2, 3, 10, 4, 6, 8, 7, 5, 9,
change 3,4
B 1, 2, 3, 4, 10, 6, 8, 7, 5, 9,
change 4,8
B 1, 2, 3, 4, 5, 6, 8, 7, 10, 9,
change 6,7
B 1, 2, 3, 4, 5, 6, 7, 8, 10, 9,
change 8,9
B 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
Press any key to continue

【说明】
以上是对6楼交换策略的实现
不过,6楼的交换策略找到的有可能只是近似解而并不是最优解……
回复
linren 2009-08-11
1 01 0 1 :A
0 01 1 1 :B

【标尺】
0 11 0 1 首先判断A、B中哪些位不同,相同的位不用交换(可以标记为1),不同的位需要进行交换(标记为1)

0 01 1 1 B
1 01 0 1 交换1次=A

关于交换的策略
有以下的一种思路:

依次找到标尺上为0的位
在后面为0的位中寻找满足的条件进行交换……

寻找时
优先选取交换后两位都满足条件的数

置当交换后满足条件的位为1……
寻找下一个标尺为0的位

如果没有找到符合条件的数
返回-1表示不能通过交换把B变成A
回复
nandizhu 2009-08-11
要是最少的 对换。。。比如上面两个序列只需要对换1,4位置即可
回复
nandizhu 2009-08-11
那样会是最少的交换吗??? 因为序列里可以允许有相同的值
比如 A:10101
B:00111

怎么排序?
回复
hyram 2009-08-11
先对B序列排序,然后每一位查找,交换,O(nlog(n))
回复
Paradin 2009-08-11
mark
找圈圈。
回复
fire_woods 2009-08-11
有O(nlog(n))时间复杂度的算法.
回复
发动态
发帖子
数据结构与算法
创建于2007-08-27

3.2w+

社区成员

数据结构与算法相关内容讨论专区
申请成为版主
社区公告
暂无公告