程序员常用的10个算法

1.二分查找算法(非递归)

 此篇写的是非递归算法,递归的在之前的查找算法中写过了。

1.1 算法的适用条件

二分查找只适用于从有序的数列中进行查找(比如数字和字母等),将数列排序后在查找。

1.2算法的效率:

时间复杂度为O(log2 n)

实例:使用二分查找的非递归形式对数组{1 3 8 10  11 67 100}进行查找

public class BinarySearchNoRecur {

    public static void main(String[] args) {
        //测试
        int[] arr = {1,3, 8, 10, 11, 67, 100};
        int index = binarySearch(arr, 100);
        System.out.println("index=" + index);//
    }

    //二分查找的非递归实现
    /**
     *
     * @param arr 待查找的数组, arr是升序排序
     * @param target 需要查找的数
     * @return 返回对应下标,-1表示没有找到
     */
    public static int binarySearch(int[] arr, int target) {

        int left = 0;
        int right = arr.length - 1;
        while(left <= right) { //说明继续查找
            int mid = (left + right) / 2;
            if(arr[mid] == target) {
                return mid;
            } else if ( arr[mid] > target) {
                right = mid - 1;//需要向左边查找
            } else {
                left = mid + 1; //需要向右边查找
            }
        }
        return -1;
    }

}

2.分治算法

2.1 分治算法介绍

1)分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题.....直到最后子问题可以简单的直接求解,原问题的姐即子问题的解的合并。这个技巧是很多高效算法的基础,入排序算法(快排,归并排序),傅里叶变换(快速傅里叶变换)...

2)分治算法可以求解的一些经典问题

二分搜索, 大整数乘法,棋盘覆盖,合并排序,快速排序,线性时间选择,最接近点对问题 ,循环赛日称表,汉诺塔等问题。

2.2 分治算法的基本步骤

分治算法在每一层递归上都有三个步骤

1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题

2)解决:若干问题规模较小而容易被解决则直接解,否则递归地解决各个子问题

3)合并:将各个子问题的解合并为原问题的解。

2.3 分治(Divide-and Conquer(P))算法设置模式:

2.4 分治算法的实践:汉诺塔(有ABC 三个塔)

2.5 思路:

1)如果是一个盘,A->C

如果我们有n>=2个盘,我们总是可以看做是两个盘:1.最下面的盘 2.上面的盘

(1)先把最上面的盘A->B

(2) 把下面的一个盘A->C

(3)把B塔的所有盘从B->C

2.6 代码实现:

public class Hanoitower {

    public static void main(String[] args) {
        hanoiTower(10, ‘A‘, ‘B‘, ‘C‘);
    }

    //汉诺塔的移动的方法
    //使用分治算法

    public static void hanoiTower(int num, char a, char b, char c) {
        //如果只有一个盘
        if(num == 1) {
            System.out.println("第1个盘从 " + a + "->" + c);
        } else {
            //如果我们有 n >= 2 情况,我们总是可以看做是两个盘 1.最下边的一个盘 2. 上面的所有盘
            //1. 先把 最上面的所有盘 A->B, 移动过程会使用到 c
            hanoiTower(num - 1, a, c, b);
            //2. 把最下边的盘 A->C
            System.out.println("第" + num + "个盘从 " + a + "->" + c);
            //3. 把B塔的所有盘 从 B->C , 移动过程使用到 a塔
            hanoiTower(num - 1, b, a, c);

        }
    }

}

3.动态规划算法

应用场景-背包问题

1.动态规划算法介绍:

1)动态规划算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法

2)动态规划算法与分治算法类似,其思想也是将待求问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

3)与分治法不同的是,适合于动态规划求解的问题,经分解得到的子问题往往不是相互独立的。(即下一个子阶段的求解是建立在上一个子阶段的解的基础上进行进一步的求解)

4)动态规划可以通过填表的方式来逐步推进,得到最优解。

2.完全背包与01背包

完全背包指的是:每种物品都有无线件可以使用;01背包只能每件物品取一个。

3.思路与图解:

代码实现:

public class KnapsackProblem {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] w = {1, 4, 3};//物品的重量
        int[] val = {1500, 3000, 2000}; //物品的价值 这里val[i] 就是前面讲的v[i]
        int m = 4; //背包的容量
        int n = val.length; //物品的个数

        //创建二维数组,
        //v[i][j] 表示在前i个物品中能够装入容量为j的背包中的最大价值
        int[][] v = new int[n+1][m+1];
        //为了记录放入商品的情况,我们定一个二维数组
        int[][] path = new int[n+1][m+1];

        //初始化第一行和第一列, 这里在本程序中,可以不去处理,因为默认就是0
        for(int i = 0; i < v.length; i++) {
            v[i][0] = 0; //将第一列设置为0
        }
        for(int i=0; i < v[0].length; i++) {
            v[0][i] = 0; //将第一行设置0
        }

        //根据前面得到公式来动态规划处理
        for(int i = 1; i < v.length; i++) { //不处理第一行 i是从1开始的
            for(int j=1; j < v[0].length; j++) {//不处理第一列, j是从1开始的
                //公式
                if(w[i-1]> j) { // 因为我们程序i 是从1开始的,因此原来公式中的 w[i] 修改成 w[i-1]
                    v[i][j]=v[i-1][j];
                } else {
                    //说明:
                    //因为我们的i 从1开始的, 因此公式需要调整成
                    //v[i][j]=Math.max(v[i-1][j], val[i-1]+v[i-1][j-w[i-1]]);
                    //v[i][j] = Math.max(v[i - 1][j], val[i - 1] + v[i - 1][j - w[i - 1]]);
                    //为了记录商品存放到背包的情况,我们不能直接的使用上面的公式,需要使用if-else来体现公式
                    if(v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
                        v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
                        //把当前的情况记录到path
                        path[i][j] = 1;
                    } else {
                        v[i][j] = v[i - 1][j];
                    }

                }
            }
        }

        //输出一下v 看看目前的情况
        for(int i =0; i < v.length;i++) {
            for(int j = 0; j < v[i].length;j++) {
                System.out.print(v[i][j] + " ");
            }
            System.out.println();
        }

        System.out.println("============================");
        //输出最后我们是放入的哪些商品
        //遍历path, 这样输出会把所有的放入情况都得到, 其实我们只需要最后的放入
//        for(int i = 0; i < path.length; i++) {
//            for(int j=0; j < path[i].length; j++) {
//                if(path[i][j] == 1) {
//                    System.out.printf("第%d个商品放入到背包\n", i);
//                }
//            }
//        }

        //动脑筋
        int i = path.length - 1; //行的最大下标
        int j = path[0].length - 1;  //列的最大下标
        while(i > 0 && j > 0 ) { //从path的最后开始找
            if(path[i][j] == 1) {
                System.out.printf("第%d个商品放入到背包\n", i);
                j -= w[i-1]; //w[i-1]
            }
            i--;
        }

    }

}

4.KMP算法

4.1 暴力匹配算法:

4.1.1 代码实现

public class ViolenceMatch {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //测试暴力匹配算法
        String str1 = "硅硅谷 尚硅谷你尚硅 尚硅谷你尚硅谷你尚硅你好";
        String str2 = "尚硅谷你尚硅你~";
        int index = violenceMatch(str1, str2);
        System.out.println("index=" + index);

    }

    // 暴力匹配算法实现
    public static int violenceMatch(String str1, String str2) {
        char[] s1 = str1.toCharArray();
        char[] s2 = str2.toCharArray();

        int s1Len = s1.length;
        int s2Len = s2.length;

        int i = 0; // i索引指向s1
        int j = 0; // j索引指向s2
        while (i < s1Len && j < s2Len) {// 保证匹配时,不越界

            if(s1[i] == s2[j]) {//匹配ok
                i++;
                j++;
            } else { //没有匹配成功
                //如果失配(即str1[i]! = str2[j]),令i = i - (j - 1),j = 0。
                i = i - (j - 1);
                j = 0;
            }
        }

        //判断是否匹配成功
        if(j == s2Len) {
            return i - j;
        } else {
            return -1;
        }
    }

}

4.2 kmp算法

4.2.1 KMP算法介绍:

1)KMP算法是一个解决模式串在文本串是否出现过,如果出现过,最早出现的位置的经典算法。

2)Knuth-Morrirs-Pratt字符串查找算法,简称为“KMP算法”,常用于在一个文本串S内查找一个模式串P的出现位置,这个算法有Donald Knuth,Vaughan Pratt,James H.Morris三人于1977年联合发表,故取这三个人名命名此算法。

3)KMP算法就是利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间

4)参考资料:https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html

4.2.2 KMP算法的应用

原文地址:https://www.cnblogs.com/yangzhixue/p/12250719.html

时间: 2024-11-05 18:55:55

程序员常用的10个算法的相关文章

分针网——每日分享:10个程序员常用的代码简写技术

更多文章:www.f-z.cn 今天小编我给大家整理了一份10个程序员常用的代码简写技术,看懂一种是入门,全懂就是大神,你能知道几个呢? 1.三元操作符 当想写if...else语句时,使用三元操作符来代替. const x = 20;let answer;if (x > 10) { 简写: const answer = x > 10 ? 'is greater' : 'is lesser'; 也可以嵌套if语句: const big = x > 10 ? " greater

Java程序员常用英语词汇

干程序员这行实在是离不开英语,干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难.这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这些技术时往往受到语言障碍的制约,严重影响到对新技术的理解和消化.首先编程本身就依赖于英语,虽然现在技术的发展,可以使得某些开发工具在变量名和字段名中支持中文,但还未发现能够完全使用中文的编程语句.     这并不代表我们英语差,就不能编程了,下面提供一点入门级的程序员常用英语,以此为开始,迈出我们学习英语的第一步,努力学习

600个程序员常用的单词和词汇

来自:网络 一小时轻松掌握程序员单词 1小时搞定程序员单词 集结了600个程序员常用的单词和词汇,让你写代码变量命名 so easy!!! 还等什么!GOGOGO! application 应用程式 应用.应用程序 application framework 应用程式框架.应用框架 应用程序框架 architecture 架构.系统架构 体系结构 argument 引数(传给函式的值).参见 parameter 参数.实质参数.实参.自变量 array 阵列 数组 arrow operator

代码面试最常用的10大算法

摘要:面试也是一门学问,在面试之前做好充分的准备则是成功的必须条件,而程序员在代码面试时,常会遇到编写算法的相关问题,比如排序.二叉树遍历等等. 在程序员的职业生涯中,算法亦算是一门基础课程,尤其是在面试的时候,很多公司都会让程序员编写一些算法实例,例如快速排序.二叉树查找等等. 本文总结了程序员在代码面试中最常遇到的10大算法类型,想要真正了解这些算法的原理,还需程序员们花些功夫. 1.String/Array/Matrix 在Java中,String是一个包含char数组和其它字段.方法的类

代码最常用的10大算法

摘要:面试也是一门学问,在面试之前做好充分的准备则是成功的必须条件,而程序员在代码面试时,常会遇到编写算法的相关问题,比如排序.二叉树遍历等等. 在程序员的职业生涯中,算法亦算是一门基础课程,尤其是在面试的时候,很多公司都会让程序员编写一些算法实例,例如快速排序.二叉树查找等等. 本文总结了程序员在代码面试中最常遇到的10大算法类型,想要真正了解这些算法的原理,还需程序员们花些功夫. 1.String/Array/Matrix 在Java中,String是一个包含char数组和其它字段.方法的类

程序员常用网站

程序员常用网站 名称:w3schools 地址:http://www.w3schools.com/ 描述:这个网站大家再熟悉不过了,W3Schools是于1999年创立的一个网站开发教程门户.W3Schools由位于挪威提供软件开发.咨询的Refsnes Data公司所成立,提供的免费网页开发教程包括HTML.XML.CSS.JavaScript.PHP.ASP等等. 名称:StackOverflow  地址:www.stackoverflow.com 描述:这个就不需要我来做更多的介绍,相信每

【常用软件】木木的常用软件点评(2)------VC程序员常用工具篇

摘自:http://blog.csdn.net/liquanhai/article/details/7215045 木木的常用软件点评(2)------VC程序员常用工具篇 分类: VC++经验总结2012-01-25 14:02 14091人阅读 评论(56) 收藏 举报 工具tortoisesvn文本编辑html加密 过年了,事情可以暂时放一下了.总结一下很有必要.又看到外面饭馆写着“岁末收工,初六开炉“了.好了,废话不多说,接着上篇继续评点程序员常用工具.当然还得请朋友们留言,好做继续的整

【算法】代码面试最常用的10大算法

http://www.csdn.net/article/2014-04-10/2819237-Top-10-Algorithms-for-Coding-Interview 在程序员的职业生涯中,算法亦算是一门基础课程,尤其是在面试的时候,很多公司都会让程序员编写一些算法实例,例如快速排序.二叉树查找等等. 本文总结了程序员在代码面试中最常遇到的10大算法类型,想要真正了解这些算法的原理,还需程序员们花些功夫. 1.String/Array/Matrix 在Java中,String是一个包含cha

Java程序员常用工具类库

有人说当你开始学习Java的时候,你就走上了一条不归路,在Java世界里,包罗万象,从J2SE,J2ME,J2EE三大平台,到J2EE中的13中核心技术,再到Java世界中万紫千红的Framework......等等,你会发现自己总是在学习,但总是有自己不知道的东西. 当你看到代码工程的lib下各种各样的jar文件的时候,你是否能全部知道他们都是干什么用的,为什么要导入到工程下吗? 从Google你能搜索到大量的关于Struts,Spring,Hibernate,iBatis等比较大的框架的资料