PAT1005 继续(3n+1)猜想

卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。

当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。

现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。

输入格式:

每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<),第 2 行给出 K 个互不相同的待验证的正整数 n (1)的值,数字间用空格隔开。

输出格式:

每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。

输入样例:

6
3 5 6 7 8 11

输出样例:

7 6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ConsoleApp5
{
    class Program
    {
        static int Main(string[] args)
        {
            //输入数列的长度
            int number = Convert.ToInt32(Console.ReadLine());
            //列表用来存放最后筛选出来的关键数,方便进行排序
            List<int> li = new List<int>();
            //用来存储输入的数列的各个数
            string[] befnum = new String[number];
            //用来存放一个数的卡拉兹数列
            int[] solvenum = new int[50];
            //用来存放关键数,由上述列表转化而来
            int[] keynum = new int[number];
            int j = 0;
            int copy = 0;
            int m = 0;
            int n = 0;
            //定义一个二位数组,第一个维度表示数列中的对应数字,第二个维度做为标识符
            int[,] record = new int[number, 1];
            //输入的数列
            string info = Console.ReadLine();
            //输入的数列按空格分割成各个数
            befnum = info.Split(' ');
            //初始化record数组
            for (int i = 0; i < number; i++)
            {
                record[i, 0] = 0;
            }
            //记录数列中每个数的卡拉兹数列
            for (int i = 0; i < number; i++)
            {
                copy = Convert.ToInt32(befnum[i]);
                j = 0;
                while (copy != 1)
                {
                    if (copy % 2 == 0)
                    {
                        solvenum[j] = copy;
                        copy = copy / 2;
                        j++;
                    }
                    else
                    {
                        solvenum[j] = copy;
                        copy = (3 * copy + 1) / 2;
                        j++;
                    }
                }
                //当前数列
                for (int l = 0; l < number; l++)
                {
                    n = 0;
                    //猜想中的数字
                    //将当前数列中的每一个数和每个数的猜想数列的各个数比较
                    for (int k = 0; k < j; k++)
                    {
                        //如果比较的数是自身就跳过,因为卡拉兹数列的第一个数是他本身
                        if (Convert.ToInt32(befnum[l]) == solvenum[k])
                        {
                            break;
                        }
                        else
                        {
                            //非自身的数但是被覆盖,卡拉兹数列有数和他相同,结束循环
                            if (Convert.ToInt32(befnum[l]) == solvenum[k])
                            {
                                break;
                            }
                        }
                        //一轮比较下来,既不是自身又没被覆盖则记录符号+1
                        n++;
                        //j为卡拉兹数列的长度,一轮下来这个数和卡拉兹数列中的每个数都不相同
                        if (n == j)
                        {
                            //二维标识符++
                            record[l, 0]++;
                        }

                    }
                }

            }
            for (int k = 0; k < number; k++)
            {
                //排除自身当这个数和输入数列中每个数的卡拉兹数列中的各个数都不相同即标识符等于输入数列长度-1
                if (record[k, 0] == number - 1)
                {
                    //往列表中加入关键数
                    li.Add(Convert.ToInt32(befnum[k]));
                    m++;
                }
            }
            //对列表进行排序
            li.Sort();
            keynum = li.ToArray();
            for (int i = 0; i < m - 1; i++)
            {
                Console.Write(keynum[i]);
                Console.Write(" ");
            }
            //最后一个数不带空格
            Console.WriteLine(keynum[m - 1]);
            return 0;
        }
    }
}

这是第一次做的思路,做复杂了,答案输出没有问题但是在PAT官网提交出现了问题求大神help

 

 之后换了一种思路

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp5
{
    class Program
    {
        static int Main(string[] args)
        {
            int type = 0;
            int copy = 0;
            int t = 0;
            //输入数列的长度
            int count = Convert.ToInt32(Console.ReadLine());
            //输入数列
            string info = Console.ReadLine();
            //存储后续关键数
            int[] answer = new int[count];
            int[] key = new int[666];
            //根据空格分割数列
            string[] number = info.Split(' ');
            //存放输入数列中的各个数
            int[] realnum = new int[count];
            //初始化key数组
            for (int i = 0; i < 666; i++)
            {
                key[i] = 0;
            }
            //将字符串数组转换为整形数组
            for (int i = 0; i < count; i++)
            {
                realnum[i] = Convert.ToInt32(number[i]);
            }
            //冒泡排序,这部我之前没想到,先排序再处理,筛选后的数还是在原来排序基础上的
            for (int i = 0; i < count - 1; i++)
            {
                for (int j = 0; j < count - 1 - i; j++)
                {
                    if (realnum[j] > realnum[j + 1])
                    {
                        type = realnum[j];
                        realnum[j] = realnum[j + 1];
                        realnum[j + 1] = type;
                    }
                }
            }
            //检查key,将输入数列中的各个数的卡拉兹数列中的各个数用key数组标识,用卡拉兹数列中的数做为下标,并把以这个下标的key数组中的数置为1
            for (int i = 0; i < count; i++)
            {
                copy = realnum[i];
                while (copy != 1)
                {
                    if (copy % 2 == 0)
                    {
                        copy = copy / 2;
                    }
                    else
                    {
                        copy = (3 * copy + 1) / 2;
                    }
                    key[copy] = 1;
                }

            }
            //这个思路是将输入数列中的数和卡拉兹数列中各个数实现一个映射关系,通过key数组这个中介
            //判断key数组中以输入数列中的数做为下标的数是否为1,若为1表示被覆盖,为2则表示是关键数
            for (int i = 0; i < count; i++)
            {
                if (key[realnum[i]] == 0)
                {
                    //存入answer数组中
                    answer[t] = realnum[i];
                    t++;
                }

            }
            //将关键数输出,每个数之间有个空格最后一个数不带空格
            int k = 0;
            for (k = 0; k < t - 1; k++)
            {
                Console.Write(answer[k]);
                Console.Write(' ');
            }
            Console.Write(answer[k]);
            return 0;
        }
    }
}

在VS上测试没有问题,放到PAT上还是之前的错误求大神指点

 

 我不知道错误错在哪里,还有我return 0了为啥还会有非零返回

posted on 2019-12-03 20:43  二进制dd  阅读(154)  评论(0编辑  收藏  举报

导航