zoukankan      html  css  js  c++  java
  • 算法题摘录五

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6437550.html

    心得:在读完题目对普遍输入的处理有了初步构思后,要往空输入、溢出、无效输入等情况去寻找函数漏洞,编码时一一处理特殊的输入。

    编码前先设置测试用例!

    1:反转句子中的单词顺序,但单词本身的字符顺序不变,如:i am a student->student a am i

    Java解法:Java提供了split()方法,我们可以直接用String[] strs=inputstring.split(" ");获得句子的单词,然后倒序遍历strs输出即可。

    C++解法:首先反转整个句子的字符顺序,然后对每个单词字符再逐个反转回来。定义一个反转函数从begin到end交换头尾指针所指。然后定义一个区分单词的函数:寻找空格所在从而确定单词字符串的begin、end,然后调用反转函数把单词字符再反转回来即可。

    2:左旋字符串:把字符串的前n个字符保持顺序移动到字符串的后面。比如: abcde移动前二——>cdeab。

    Java解法:用StringBuilder把字符串字符重新拼接就好。

    C++解法:我们把整个字符串反转后发现abcde->edcba,把字符串分为两部分来反转:edc->cde,ba->ab,结果变为cdeab,就是我们要得到的结果。那么我们就可以得到解题思路了:先把字符串反转,然后对字符串的后n个字符的字符串反转,再对0~n-1段字符反转,即可实现左旋。思路同上一题,定义一个反转函数,再定义一个函数来控制反转的下标范围。

    3:投n个骰子,求面朝上的点数和S的所有值出现的概率。

     我们来模拟一下:

    假设已有的骰子和为S的次数为k,现在我们来增加一个骰子;新的骰子只会出现1~6中随机一个的一次,为保持和仍为S,那么剩下就要投出和为 S-6~S-1 的情况。我们用一个数组sum_count[]来保存骰子们和的情况,第S个说明骰子和为S出现的次数。由上面描述可知,每新增一个骰子,为保持和为S,则次数为 sum_count(S-6)+...+sum_count(S-1)为新的和为S的次数。

    void probablyCount(int num,int MaxValue){
            if(num<1){
                return;
            }
            int[][] counts=new int[2][num*MaxValue+1];
            
            for(int i=0;i<MaxValue*num+1;++i){
                counts[0][i]=0;
                counts[1][i]=0;
            }
            int which_count=0;
            //1个骰子时,数组前6位记录和为1~6出现的次数
            for(int i=1;i<=MaxValue;++i){
                counts[which_count][i]=1;
            }
            //逐步增加骰子,骰子的和也逐步增加。而和为M就记录在第M下标
            for(int k=2;k<=num;++k){
                for(int i=0;i<k;++i){
                    counts[1-which_count][i]=0;
                }
                for(int i=k;i<=k*MaxValue;++i){//i记录了K个骰子的点数和k~k*MaxValue
                    counts[1-which_count][i]=0;//用另一个数组记录点数i的次数,先置0
                    //j是新增的骰子的点数范围:1~Max,且j的点数要小于和
                    for(int j=1;j<=i && j<=MaxValue;++j){
                        //那么和为i的次数等于 i-j的次数和
                        counts[1-which_count][i]+=counts[which_count][i-j];
                    }
                }
                which_count=1-which_count;
            }
            double total=Math.pow(MaxValue, num);
            for(int i=num;i<=num*MaxValue;++i){
                System.out.println("Count="+i+",Radio="+counts[which_count][i]/total);
            }
        }

     4:扑克牌顺子判断

    抽5张扑克牌,判断是不是顺子。扑克牌A=1,J=11,Q=12,K=13,大小王可以看作任意数字。

    既然我们可以把JQK转换成数字,我们不妨把大小王也转换成0,也就是说数组中的0就可以转换成任意数字。

    这样思路就清晰了:把这5张牌用一个int[5]数组保存起来,注意存的时候JQK和大小王转为相应数字。然后对数组排序。如果有大小王,那么数组前面绝对是0.我们先来统计0的个数,得到king_count;然后从非0的第一个元素开始,统计递增序列的间隔数lack_count;然后比较king_count与lack_count即可,如果0大于等于lack_count,说明可以用大小王补间隔成为顺子。特殊情况:非0元素有对子出现,那么决定不是顺子,在统计间隔的时候增加一条如果当前元素与下一元素相等,则直接返回false。(由于间隔统计是从第一个非0元素开始的,所以不会统计到前面的相同0)。

    5:每次删除圆环中第m个数字,求最后剩下的数字——Josephuse环问题

    传统解法:用一个环形链表模拟圆环,每次遍历m步删除所指结点;

    优化解法:我们发现:n结点时删除第m个数字最终剩下的数字下标last,由(last+m)%n可以得到n+1个结点时删除第m个数字最终剩下的数字下标。根据此递推式,所以我们用递归或者循环就可以从2开始推导出来。注意:只有1个结点时不成环,返回-1.

    6:求1+2+...+n

    高斯定理的使用:1+2+...+n=n(n+1)/2

    发散思维:构造函数求法:定义两个全局变量:num、sum,在一个类的构造函数中进行num++,sum+=num;然后创建一个包含n个类对象的数组即可调用n次构造函数,而这n个对象依次创建就得到了1+2+3+...+n

    7:把字符串转换成数字:

    字符串除了是常规的数字字符串外,还可能是null、可能会溢出、可能是包含+-*/号的表达式、可能是+-数,还可能是非数字的无效输入。

    常规输入的求法:sum=sum*10+num[i++];(i<=num.length)

    8:求一棵树中两个结点的最近公共祖先。

    如果是BST树:我们可以用递归查找:两个结点都在比根小,则在左边,递归左子树直到两结点分别位于当前根结点的两边,那么当前根节点即为所求;同理右边也是;

    如果是普通树:我们可以用两个辅助链表,分别保存根节点到这两个结点的路径;然后问题转化为求两个链表的最右一个公共结点:因为根到最后一个公共结点段是相同的,之后才分叉。

    9:找到数组中的重复数字

    传统解法:用hashmap,遍历数组,用map.get(nums[i])判断是否已有这个元素,没有则map.put(),有返回则说明前面已出现过,此元素重复;

    优化解法:用交换法把数字n放到下标n处——i从0开始遍历,若nums[i]==i,说明nums[i]处于合适位置;若nums[i]==j,比较nums[i]与nums[j],相等这说明i重复;不等则把nums[i]与nums[j]交换,把j放到合适的地方去。

    10:给定数组A[n],令B[i]=A[0]*A[1]*...*A[i-1]  *  A[i+1]*...*A[n-1],求数组B[],不能使用除法。

    定义一个连乘函数multi(int1,int2)计算A[int1]到A[int2]的连乘积;然后B[i]=multi(0,i-1)*multi(i+1,n-1)。

     

     

  • 相关阅读:
    不开心吗?那来看看这组治愈漫画吧!
    TF、Keras错误解决:TypeError: Cannot interpret feed_dict key as Tensor ...... is not an element of this graph.
    【JMeter】HTTP请求示例以及事务控制器的使用
    <%=BASE_URL%>根目录
    vue循环多个form表单,v-model绑定值一样的问题。
    vue 具名插槽
    vue 实现子组件改变数据,父组件实时更新 (使用.sync修饰符就可以实现)
    vue-cli3快速创建项目
    js关于Blob对象的使用
    AnyCAD C#开发-TopoShapeConvert辅助类TopoShape转换为SceneNode
  • 原文地址:https://www.cnblogs.com/ygj0930/p/6437550.html
Copyright © 2011-2022 走看看