zoukankan      html  css  js  c++  java
  • shell练习--PAT题目1005:继续(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
    分析:
      1.应该可以用关联数组的值判断是否为最小值。
      2.要理解覆盖关系的问题,可以用1001的脚本分别跑一下这几个数字,就可以发现,对于 3 5 6 8 来说,存在一个包含与被包含的关系:6 → 3 → 5 → 8,对于7 11而言,存在 7 → 11的关系。
    那么可以通过判断数字n是不是在上一个数字的数组里面可以判断是否存在覆盖的问题。
    初步思路为:
      1.按照1001示例中,将每个数值的结果存入关联数组中;
      2.当存在值的覆盖时,对于关联数组中该值的数值+1;
      3.判断关联数组中,所有值为1的数值;
      4.将步骤3中的数值,与输入数组的值,当存在步骤三,且存在输入值时,判断输出。
    wyf349@ubuntu:~/user/study_shell$ ./1005.callatz.err1.sh  #增加一个数组存放中间值,打印
    input n:3
    5 8 4 2 1
    wyf349@ubuntu:~/user/study_shell$ ./1005.callatz.err1.sh 
    input n:5
    8 4 2 1
    wyf349@ubuntu:~/user/study_shell$ ./1005.callatz.err1.sh 
    input n:6
    3 5 8 4 2 1
    wyf349@ubuntu:~/user/study_shell$ ./1005.callatz.err1.sh 
    input n:8
    4 2 1
    

      具体代码如下,目前尚未通过:

        随机了1-100的随机数,和其他人通过的C语言,python的结果比对一致,不知道异常案例的情况下,也没有太好的思路。

        运行超时是一定的了。

    #/bin/bash
    #校验Callatz规则
    func_check(){
            if [ `expr $n % 2` -eq 0 ]
            then
                    n=`echo "$n/2" |bc `
            else
                    n=`echo "((3*$n)+1)/2" |bc `
            fi
    }
    
    read number 
    read  str  #输入字符组,此处没有解决多行直接输入问题,使用-d参数可以多行,但需要指定结束符,索性忽略首行
    arr_tmp=($str)
    if [ $number -gt 0 -a $number -le 100 ] && [ ${#arr_tmp[@]} -eq $number ] && [ $number -gt 1 ] 
    then
        pass
    else
        echo "输入不满足条件,请检查输入值!"
        exit 1
    fi
    
     
    declare -A arr_n  #定义关联数组 arr_n
     
    for n in $(echo $str)
    do
        if [ $n -gt 0 -a $n -lt 100 ];then pass ;else exit && exit 1;fi 2>/dev/null
        arr=($n)   #把输入作为第一个元素
        i=1
        while [ $n != 1 ]  
        do
            func_check
            arr[$i]=$n
            let i++
        done
        #echo ${arr[@]}
        for j in ${arr[@]} 
        do
            let arr_n[$j]++   #统计关联数组的个数,相同的自增
        done    
    done
    
    list_tmp='' 
    for arr_title in  ${!arr_n[@]}
    do
            echo $str |grep -wq $arr_title   #判断数字是否在输入数字中
            if [ $? -eq 0 ] 
            then
                    list=$(echo ${arr_title} ${arr_n[${arr_title}]} |awk '{if($2==1) print $1}')
                    list_tmp="$list_tmp $list"
            fi
     
    done
    list_tmp=(`echo $list_tmp | tr ' ' '
    ' |sort -n -r |tr '
    ' ' '`)
    echo ${list_tmp[@]} 
    

      python的方法(相同思路通过),但是不简洁,新增了很多列表

    def callate2(x):   #定义一个函数计算callate的值的列表
        list_tmp1=[]
        list_tmp1.append(x)
        while x != 1 :
            if x % 2 == 0:
                x = x / 2
            else:
                x = (3 * x + 1) / 2
            list_tmp1.append(int(x))
        return list_tmp1
    
    n = int(input())
    list=[int(x) for x in input().split()]
    new_list=[]
    
    for i in list:
        a = callate2(i)
        new_list.append(a)
    new_list_1=[]
    for i in range(len(new_list)):   #解包,将列表new_list中的元素解包
        for j in range(len(new_list[i])):
            new_list_1.append(new_list[i][j])
            
    new_dict={}
    for x in new_list_1:
        new_dict[x]=new_list_1.count(x)
    
    list_a=[]                    #筛选元素为1的值
    for k,v in new_dict.items():
        if v == 1 :
            list_a.append(k)
    
    set_a=set(list_a).intersection(set(list))  #集合的方法,交集
    list_b=[x for x in set_a]
    list_b.sort()   #排序,sort方法直接修改原列表,不产生新的对象。
    list_b.reverse()
    print(' '.join(str(x) for x in list_b)) #join方法前提是元素为字符串形式
    

      

      

  • 相关阅读:
    【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理
    【bzoj4832】[Lydsy1704月赛]抵制克苏恩 期望dp
    【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分
    【bzoj3309】DZY Loves Math 莫比乌斯反演+线性筛
    【bzoj2813】 奇妙的Fibonacci数列 线性筛
    面向对象实现简单的学生课程选择
    小案例--面向对象中实现分页
    初识面向对象四(装饰器/反射)
    python小技巧--控制台输出带颜色的文字方法
    初识面向对象三(经典类/多态/鸭子类型/初识封装)
  • 原文地址:https://www.cnblogs.com/wyf-349/p/11245649.html
Copyright © 2011-2022 走看看