CCF题目1—P1540 机器翻译
从今天开始刷算法题。
自己的思路:
* 思路:
* 先定义两个数组,将第一个数组的数据都定为-1;
* 第二个数组存放数据,并定义一个指针指向0号索引;
* 定义一个计数器;
* 先检查有没有相同的,如果没有,当检查到数据为-1时,将数据替换-1;
* 当没有-1数据时,遍历数组,寻找数组中是否已存在该数据,是则不做变化;
* 否则数组前移1位,并把数据存入最后一位,计数器+1;
但是发现这种思路写起来,会有很大的局限性,比如数据量大了很繁琐,而且没用的代码量也比较多。
根据题意所以简略了一下思路:
判断是否存在该元素,是则使用continue跳过本次循环,否则对数组内的数据前移一位,最后一位赋值为新元素,并计数
同时,在编代码的过程中,由于不熟悉部分代码语法,还是通过百度了一下语法,并通过调试来输出显示。
其实这样虽然结果是正确的,但过程跟题目给的顺序是不一样的。
而且为了在网页上测试通过,还得严格按照网址上的格式进行修改才能通过编译。
以下是源代码:写的较差,仅供参考
package CCF.P1540;
//package CCF;
//package CCF;//day01——P1540——机器翻译
import java.util.Arrays;
import java.util.Scanner;
public class Main
{
/*
* 需求:
* 两个数组,一个M,一个N;
* 前者定义一个数组大小,后者定义数据的个数;
* 遍历每个数据,当数组没满时,将数据存入数组;
* 当数组中存在该数据时不作改变;
* 当不存在时,将该数据替换数组最后一位
*
* 思路:
* 先定义两个数组,将第一个数组的数据都定为-1;
* 第二个数组存放数据,并定义一个指针指向0号索引;
* 定义一个计数器;
* 先检查有没有相同的,如果没有,当检查到数据为-1时,将数据替换-1;
* 当没有-1数据时,遍历数组,寻找数组中是否已存在该数据,是则不做变化;
* 否则数组前移1位,并把数据存入最后一位,计数器+1;
*
* 判断是否存在该元素,是则使用continue跳过本次循环,否则对数组内的数据前移一位,最后一位赋值为新元素。
*/
public static void main(String[] args) {
//输入M,N;
Scanner sc = new Scanner(System.in);
// System.out.println("请输入M:");
int M = sc.nextInt();
// System.out.println("请输入N:");
int N = sc.nextInt();
//定义数组M
int []MM = new int[M];
for(int i=0;i<M;i++)
{
MM[i] = -1;
}
//定义数组N
int []NN = new int[N];
// System.out.println("请输入数据:");
for(int i=0;i<N;i++)
{
NN[i] = sc.nextInt();
}
// System.out.println("M:"+Arrays.toString(MM));
// System.out.println("N:"+Arrays.toString(NN));
//定义计时器
int count = 0;
boolean flag = false;
for(int j=0;j<N;j++)
{
// System.out.print("第"+j+"次:"+NN[j]+" : ");
for(int k=0;k<M;k++)
{
if(NN[j]==MM[k])
{
flag = true;
break;
}
flag = false;
}
if(flag==true)
{
// System.out.println("已存在");
continue;
}
if(flag==false)
{
for(int k=0;k<M-1;k++)
{
MM[k]=MM[k+1];
}
MM[M-1] = NN[j];count++;
// System.out.println("M:"+count+" : "+Arrays.toString(MM));
}
}
System.out.println("M:"+Arrays.toString(MM));
System.out.println("N:"+Arrays.toString(NN));
System.out.println("需要查询:"+count+"次");
System.out.println(count);
}
}
可见性能优化封面还是比较差的,而且也只用到了数组的知识,测试了一下发现目前自己的代码能力还是比较差,需要多多学习和练习。
然后根据网上的代码发现了一种新的思路,用到了队列和数组判断,比我自己的思路更加灵活。
队列相关知识:
基于先进先出的方式:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
思路:
可以看成一个队列的问题
检测队列中是否存在,可以使用一个p数组,长度为1001 因为题目要求0≤N≤1000 默认p数组每一个都为0,只要p[N]==0
就队列不存在这个元素,相当于一个map一一对应 N相当于p的下标 只要检测N作为下标所对应的数是否为0就可以检测是否存在
添加后p[N]++ 这时再有同样元素,就可以知道其不为0,所以不用翻字典
当队列达到满的时候,队头出来,队尾添加元素 这时候队头元素作为下标对应的p就应该–置0 并同时把p[队尾元素]++
同时设置一个检测队列是否满的值和翻字典的次数的值即可
package CCF.P1540;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
* 思路:
可以看成一个队列的问题
检测队列中是否存在,可以使用一个p数组,长度为1001 因为题目要求0≤N≤1000 默认p数组每一个都为0,只要p[N]==0
就队列不存在这个元素,相当于一个map一一对应 N相当于p的下标 只要检测N作为下标所对应的数是否为0就可以检测是否存在
添加后p[N]++ 这时再有同样元素,就可以知道其不为0,所以不用翻字典
当队列达到满的时候,队头出来,队尾添加元素 这时候队头元素作为下标对应的p就应该--置0 并同时把p[队尾元素]++
同时设置一个检测队列是否满的值和翻字典的次数的值即可
*/
public class P1540 {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
//定义数组
int a[] = new int[m];
for(int i=0;i<m;i++)
{
a[i] = sc.nextInt();
}
//数组p判断是否存在该元素,默认设为0
int p[] = new int [1001];
//队列,先进先出
Queue<Integer> my = new LinkedList<Integer>();
int index = 0;
int count = 0;
for(int i=0;i<m;i++)
{
if(p[a[i]]==0)
{
if(index<n)
{
p[a[i]]+=1;
my.add(a[i]);
index++;
count++;
}
else
{
p[my.poll()]-=1;//弹出队列的首部元素
my.add(a[i]);//尾部添加新元素
p[a[i]]+=1;//声明元素已存在
count++;//计数
}
}
}
System.out.println(count);
}
}
总结:
通过这次较小的编程,发现了自己的编码能力实在是较弱,所以以后还会多多练习,做到学练结合。