PAT甲组1067.Sort with Swap(0, i)思路与注意点--补充《算法笔记》

A1067

题目链接

思路与注意点

整体思路:数字0在i号位,找到数字i与数字0交换位置
贪心策略:本题中,如果当前 0 处于 i 号位,则找到数字 i 当前所处的位置,然后把 0 与 i 进行交换,此时数字i 就位于它的最终位置上,取得了最优解。
Questions:
1、使用哪种数据结构进行存储可以使代码编写更简洁,查找效率更高
2、一旦当0回到0号位时,此时要如何处理
3、如何判断已经有序,算法结束
Answers:
1、充分利用数组下标与数组存储值:pos[]含义,数字所处的位置(如第一个数据数字3,num = 3, pos[3] = 0,表示3这个数字位于0号位)
2、此时与数组内没有回到自己位置的任意数字交换即可打破僵局
3、预处理得到不在本位的数字的个数cnt,每次交换可确定一个数字的位置,cnt–,指导cnt不大于0,从而标志算法结束

个人做题时的思路

我个人思路与书上思路不大相同,使用arr[]存原序列,ans[]数组存已经排好序的序列。想要时刻标记出index0的位置,用arr[]中0的位置与已经排好序的ans[]中对应位置进行比对,若不相同,则在arr[]找到与ans[]中相同的数进行交换
耗时较多的地方:在arr[]中找到对应数字,判断算法结束与否
思考:有没有以空间换时间的方法提高查找效率
方法目标:0与一个数字交换,如何能快速知道,该数字究竟在几号位?
方法:设置散列,记录数字位置编号,即书中的思路

PS:

个人思路得代码显得冗余,若无时间的严格要求,个人思路能通过。
本题的两个特殊之处,输入序列范围刚好在0~N-1之间,且要求排列顺序是递增的,与数组下标一致,所有应该充分利用数组下标与数组存储的关系

代码

#include <bits/stdc++.h>
using namespace std;
int N, ans, cnt;
int pos[100005];
bool cmp(int a, int b)
{
 return a < b;
}
void swaparr(int &a, int &b)
{
 int temp = a;
 a = b;
 b = temp;
}
int main(int argc, char *argv[]) {
 scanf("%d", &N);
 cnt = N - 1;//记录0以外不在本位的个数,即数字未出现在对的位置 
 for(int i = 0; i < N; i++)
 {
  int num;
  scanf("%d", &num);
  //如:3这个数字出现在0号位上 
  pos[num] = i;//存放当前数字出现在几号位上,即数组的下标
  if(num == i && num != 0)//当对的数字出现在对的位置,如3在3号位上时 
  {
   cnt--; 
  } 
 }
 int index = 1;
 while(cnt > 0)
 {
  if(pos[0] == 0)//如果0在0号位上 
  {
   while(index < N)
   {
    if(pos[index] != index)
    {
     swaparr(pos[0], pos[index]);
     ans++;
     //cnt--;//此处只是找到任一个不在本位上的数进行交换,并不能保证一定会换回到正确位置 
     break;
    }
    index++;
   } 
  }
  while(pos[0] != 0)
  {
   swaparr(pos[0], pos[pos[0]]);
   ans++;
   cnt--;
  }
 }
 printf("%d", ans);
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值