动态编程主要用来解决如下技术问题:

  • An instance is solved using the solutions for smaller instances;
  • 对于一个较小的实例,可能需要许多个解决方案;
  • 把较小实例的解决方案存储在一个表中,一旦遇上,就很容易解决;
  • 附加空间用来节省时间。

上面所列的爬台阶问题完全符合这四个属性,因此,可以使用动态编程来解决:

1
2
3
4
5
6
7
8
9
10
11
12
public static int[] A = new int[100];
  
public static int f3(int n) {
    if (n <= 2)
        A[n]= n;
  
    if(A[n] > 0)
        return A[n];
    else
        A[n] = f3(n-1) + f3(n-2);//store results so only calculate once!
    return A[n];
}

一些基于动态编程的算法:

编辑距离

From Wiki:

In computer science, edit distance is a way of quantifying how dissimilar two strings (e.g., words) are to one another by counting the minimum number of operations required to transform one string into the other.

There are three operations permitted on a word: replace, delete, insert. For example, the edit distance between “a” and “b” is 1, the edit distance between “abc” and “def” is 3. This post analyzes how to calculate edit distance by using dynamic programming.

Key Analysis

Let dp[i][j] stands for the edit distance between two strings with length i and j, i.e., word1[0,...,i-1] and word2[0,...,j-1].
There is a relation between dp[i][j] and dp[i-1][j-1]. Let’s say we transform from one string to another. The first string has length i and it’s last character is “x”; the second string has length j and its last character is “y”. The following diagram shows the relation.

  1. if x == y, then dp[i][j] == dp[i-1][j-1]
  2. if x != y, and we insert y for word1, then dp[i][j] = dp[i][j-1] + 1
  3. if x != y, and we delete x for word1, then dp[i][j] = dp[i-1][j] + 1
  4. if x != y, and we replace x with y for word1, then dp[i][j] = dp[i-1][j-1] + 1
  5. When x!=y, dp[i][j] is the min of the three situations.

Initial condition:
dp[i][0] = i, dp[0][j] = j

Java Code

After the analysis above, the code is just a representation of it.

public static int minDistance(String word1, String word2) {int len1 = word1.length();int len2 = word2.length();// len1+1, len2+1, because finally return dp[len1][len2]int[][] dp = new int[len1 + 1][len2 + 1];for (int i = 0; i <= len1; i++) {dp[i][0] = i;}for (int j = 0; j <= len2; j++) {dp[0][j] = j;}//iterate though, and check last charfor (int i = 0; i < len1; i++) {char c1 = word1.charAt(i);for (int j = 0; j < len2; j++) {char c2 = word2.charAt(j);//if last two chars equalif (c1 == c2) {//update dp value for +1 lengthdp[i + 1][j + 1] = dp[i][j];} else {int replace = dp[i][j] + 1;int insert = dp[i][j + 1] + 1;int delete = dp[i + 1][j] + 1;int min = replace > insert ? insert : replace;min = delete > min ? min : delete;dp[i + 1][j + 1] = min;}}}return dp[len1][len2];
}
 
最长回文子串
Finding the longest palindromic substring is a classic problem of coding interview. In this post, I will summarize 3 different solutions for this problem.

1. Naive Approach

Naively, we can simply examine every substring and check if it is palindromic. The time complexity is O(n^3). If this is submitted to LeetCode onlinejudge, an error message will be returned – “Time Limit Exceeded”. Therefore, this approach is just a start, we need better algorithm.

public static String longestPalindrome1(String s) {int maxPalinLength = 0;String longestPalindrome = null;int length = s.length();// check all possible sub stringsfor (int i = 0; i < length; i++) {for (int j = i + 1; j < length; j++) {int len = j - i;String curr = s.substring(i, j + 1);if (isPalindrome(curr)) {if (len > maxPalinLength) {longestPalindrome = curr;maxPalinLength = len;}}}}return longestPalindrome;
}public static boolean isPalindrome(String s) {for (int i = 0; i < s.length() - 1; i++) {if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {return false;}}return true;
}

2. Dynamic Programming

Let s be the input string, i and j are two indices of the string.

Define a 2-dimension array “table” and let table[i][j] denote whether substring from i to j is palindrome.

Start condition:

table[i][i] == 1;
table[i][i+1] == 1  => s.charAt(i) == s.charAt(i+1)

Changing condition:

table[i][j] == 1 => table[i+1][j-1] == 1 && s.charAt(i) == s.charAt(j)

Time O(n^2) Space O(n^2)

public static String longestPalindrome2(String s) {if (s == null)return null;if(s.length() <=1)return s;int maxLen = 0;String longestStr = null;int length = s.length();int[][] table = new int[length][length];//every single letter is palindromefor (int i = 0; i < length; i++) {table[i][i] = 1;}printTable(table);//e.g. bcba//two consecutive same letters are palindromefor (int i = 0; i <= length - 2; i++) {if (s.charAt(i) == s.charAt(i + 1)){table[i][i + 1] = 1;longestStr = s.substring(i, i + 2);}   }printTable(table);//condition for calculate whole tablefor (int l = 3; l <= length; l++) {for (int i = 0; i <= length-l; i++) {int j = i + l - 1;if (s.charAt(i) == s.charAt(j)) {table[i][j] = table[i + 1][j - 1];if (table[i][j] == 1 && l > maxLen)longestStr = s.substring(i, j + 1);} else {table[i][j] = 0;}printTable(table);}}return longestStr;
}
public static void printTable(int[][] x){for(int [] y : x){for(int z: y){System.out.print(z + " ");}System.out.println();}System.out.println("------");
}

Given an input, we can use printTable method to examine the table after each iteration. For example, if input string is “dabcba”, the final matrix would be the following:

1 0 0 0 0 0
0 1 0 0 0 1
0 0 1 0 1 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1

From the table, we can clear see that the longest string is in cell table[1][5].

3. Simple Algorithm

Time O(n^2), Space O(1)

public String longestPalindrome(String s) {if (s.isEmpty()) {return null;}if (s.length() == 1) {return s;}String longest = s.substring(0, 1);for (int i = 0; i < s.length(); i++) {// get longest palindrome with center of iString tmp = helper(s, i, i);if (tmp.length() > longest.length()) {longest = tmp;}// get longest palindrome with center of i, i+1tmp = helper(s, i, i + 1);if (tmp.length() > longest.length()) {longest = tmp;}}return longest;
}// Given a center, either one letter or two letter,
// Find longest palindrome
public String helper(String s, int begin, int end) {while (begin >= 0 && end <= s.length() - 1 && s.charAt(begin) == s.charAt(end)) {begin--;end++;}return s.substring(begin + 1, end);
}

4. Manacher’s Algorithm

Manacher’s algorithm is much more complicated to figure out, even though it will bring benefit of time complexity of O(n).

单词分割

Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

For example, given
s = “leetcode”,
dict = ["leet", "code"].

Return true because “leetcode” can be segmented as “leet code”.

1. Naive Approach

This problem can be solve by using a naive approach, which is trivial. A discussion can always start from that though.

public class Solution {public boolean wordBreak(String s, Set<String> dict) {return wordBreakHelper(s, dict, 0);}public boolean wordBreakHelper(String s, Set<String> dict, int start){if(start == s.length()) return true;for(String a: dict){int len = a.length();int end = start+len;//end index should be <= string lengthif(end > s.length()) continue;if(s.substring(start, start+len).equals(a))if(wordBreakHelper(s, dict, start+len))return true;}return false;}
}

Time: O(2^n)

2. Dynamic Programming

The key to solve this problem by using dynamic programming approach:

  • Define an array t[] such that t[i]==true => 0-(i-1) can be segmented using dictionary
  • Initial state t[0] == true
public class Solution {public boolean wordBreak(String s, Set<String> dict) {boolean[] t = new boolean[s.length()+1];t[0] = true; //set first to be true, why?//Because we need initial statefor(int i=0; i<s.length(); i++){//should continue from match positionif(!t[i]) continue;for(String a: dict){int len = a.length();int end = i + len;if(end > s.length())continue;if(t[end]) continue;if(s.substring(i, end).equals(a)){t[end] = true;}}}return t[s.length()];}
}

Time: O(string length * dict size)

One tricky part of this solution is the case:

INPUT: "programcreek", ["programcree","program","creek"].

最大的子数组

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

Naive Solution

A wrong solution. Simply iterate the array like the following will not work.

public class Solution {public int maxSubArray(int[] A) {int sum = 0;int maxSum = Integer.MIN_VALUE;for (int i = 0; i < A.length; i++) {sum += A[i];maxSum = Math.max(maxSum, sum);if (sum < 0)sum = 0;}return maxSum;}
}

Dynamic Programming Solution

We should ignore the sum of the previous n-1 elements if nth element is greater than the sum.

public class Solution {public int maxSubArray(int[] A) {int max = A[0];int[] sum = new int[A.length];sum[0] = A[0];for (int i = 1; i < A.length; i++) {sum[i] = Math.max(A[i], sum[i - 1] + A[i]);max = Math.max(max, sum[i]);}return max;}
}

转载于:https://www.cnblogs.com/Free-Thinker/p/3682840.html

代码面试最常用的10大算法(四)相关推荐

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

    摘要:面试也是一门学问,在面试之前做好充分的准备则是成功的必须条件,而程序员在代码面试时,常会遇到编写算法的相关问题,比如排序.二叉树遍历等等. 在程序员的职业生涯中,算法亦算是一门基础课程,尤其是在 ...

  2. 数据科学家最常用的10种算法

    最新的KDnuggets调查统计了数据科学家们实际工作中最常使用的算法,在大多数学术和产业界,都有惊人发现哦! 根据Gregory Piatetsky, KDnuggets,最新的调查问题是:在最近的 ...

  3. 编程面试的10大算法概念汇总

    编程面试的10大算法概念汇总 嘿,第一次翻译文章,在ProgramCreek看到的,原文章名为Top 10 Algorithms for Coding Interview, 对于我这个明年即将直奔BA ...

  4. 面试10大算法汇总+常见题目解答

    http://www.programcreek.com/2012/12/%E9%9D%A2%E8%AF%9510%E5%A4%A7%E7%AE%97%E6%B3%95%E6%B1%87%E6%80%B ...

  5. 编程面试过程中最常见的10大算法

    编程面试过程中最常见的10大算法 编程语言:C/C++ 1. 字符串 如果IDE没有代码自动补全功能,所以你应该记住下面的这些方法. toCharArray() // 获得字符串对应的char数组 A ...

  6. java面试算法总结_java编程面试过程中常见的10大算法概念汇总

    以下是在编程面试中排名前10的算法相关的概念,我会通过一些简单的例子来阐述这些概念.由于完全掌握这些概念需要更多的努力,因此这份列表只是作为一个介绍.本文将从Java的角度看问题,包含下面的这些概念: ...

  7. 鸿钧老祖 数据结构笔记01:编程面试过程中常见的10大算法(java)

    以下是在编程面试中排名前10的算法相关的概念,我会通过一些简单的例子来阐述这些概念.由于完全掌握这些概念需要更多的努力,因此这份列表只是作为一个介绍.本文将从Java的角度看问题,包含下面的这些概念: ...

  8. Java数据结构与算法(九)-程序员常用的10中算法

    本章目录 第14章 程序员常用的10中算法 14.1 二分查找算法(非递归) 14.1.1 二分查找算法(非递归)介绍 14.2 分治算法 14.2.1 分治算法介绍 14.2.2 分治算法最佳实践- ...

  9. 【数据结构与算法】 常用的十大算法

    常用的十大算法: 文章目录 常用的十大算法: 1.二分查找算法(非递归): 2.分治算法 2.1分治算法介绍 2.2 分治算法的基本步骤 2.3 分治算法最佳实践-汉诺塔 2.4 动态规划算法 2.4 ...

最新文章

  1. python局域网传输文件_Python+pyftpdlib实现局域网文件互传
  2. 打印机驱动程序属于计算机硬件吗,如何安装打印机驱动程序,详细教您如何给电脑安装打印机驱动程序...
  3. Linux input子系统 io控制字段【转】
  4. 【AC自动机】病毒代码(ybtoj AC自动机-5)
  5. 采取监测记录网络运行状态_广播播控监测自动化系统改造探析
  6. 回溯 皇后 算法笔记_算法笔记-回溯法
  7. Visual Studio下使用jQuery的10个技巧
  8. PHPExcel+phalcon+yii批量导入
  9. intval0.57100 php_关于PHP浮点数之 intval((0.1+0.7)*10) 为什么是7
  10. GDAL打开HDF格式时遇到的中文路径问题(未解决)
  11. 如何根据地理位置获取城市编码 / (高德地图) 获取城市编码API / 经纬度获取城市or城市编码
  12. python2.7+pyqt4安装
  13. android 跳转京东app,第三方应用跳转到京东app
  14. win的反义词_小学英语常见的英语单词反义词大汇总,一定要让孩子掌握!
  15. pdf照片显示正常打印时被翻转_2020年广东二级建造师准考证打印常见问题
  16. 【DOORS】产品功能介绍
  17. 进入web端进行来源判断后 自动跳转至wap端页面
  18. 解决elementui的el-dialog 对话框 屏幕放大缩小不变形问题
  19. 地下管线探测重点与难点分析
  20. 2018《财富》世界500强出炉,比500强更多的财富在这里!—创成汇

热门文章

  1. 有谁知道怎么处理微信用户头像过期问题,除了本地保存,因为不会用七牛云远程附件
  2. 巴拿赫空间的基本性质
  3. Android facebook集成
  4. 男人哭了,是因为他真的爱了
  5. U盘修复“系统找不到指定文件”问题记录
  6. Java 循环语句折纸小游戏
  7. 云起实验室:零基础入门Serverless:一键部署红白机小游戏
  8. 上海住房公积金账号系统及查询
  9. 中国计算机网络设备制造业总体趋势免费版,致自己的心灵鸡汤说说,句句经典,引人深思!...
  10. 七夕情人节表白网站代码 3D流星雨旋转相册 程序员专属情人节表白网站