博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试常考编程题
阅读量:7212 次
发布时间:2019-06-29

本文共 5239 字,大约阅读时间需要 17 分钟。

1.   给定一个数组,求最大的连续子序列和,O(n)时间与O(1)空间

2.   有一个坐标轴,上面有很多点,每个点有坐标,求长度为L的绳子最多能够覆盖几个点。

    两个指针,start,end。 

    如果points[front]-points[rear]<=L,头start向前移动一步。 
    如果points[front]-points[rear]>L,尾巴end向前移动一步。 
    每个数最多遍历2遍,因此时间复杂度为O(n)。 

int maxCover(int* a, int n, int l) 5 { 6     int maxCover = 1; 7     int begin = 0; 8     int end = 1; 9     while(end < n)10     {11         if(a[end] - a[begin] > l)12         {13             maxCover = (end - begin) > maxCover?(end - begin):maxCover;14             begin++;15         }16         else17             end++;18     }19     return maxCover;20 }

 

3.   求一个数组中第k 大的数

4.   最长公共序列

      

class LCS {public:    int findLCS(string A, int n, string B, int m) {        // write code here        int dp[n + 1][m + 1];        for(int i = 0; i <= n; i++){            dp[i][0] = 0;        }        for(int j = 0; j <= m; j++){            dp[0][j] = 0;        }                for (int i = 0; i < n; i++){            for (int j = 0; j < m; j++){                if (A[i] == B[j]){                    dp[i + 1][j + 1] = dp[i][j] + 1;                }                else{                    dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);                }            }        }        return dp[n][m];    }};

 

 

5.   最长递增子序列(Longest Increasing Subsequence)是指找到一个给定序列的最长子序列的长度,使得子序列中的所有元素单调递增。

      例如:{ 3,5,7,1,2,8 } 的 LIS 是 { 3,5,7,8 },长度为 4。

 

思路:建立一个大小与 nums 长度相等的数组dp,用于记录每个 子序列的 最长长度,即 dp[i] 表示nums 第 0 个到第 i 个元素中以 nums[i]为最大值的最长子序列长度(注意序列的最后一个值为 nums[i]):

感觉底下的这个图不对。。

      

 

//  状态转移方程    dp[i] = max{dp[j]+1,dp[i]}, j
dp(n, 1); // 初始化为1 for(int i = 1; i < n; i++){ //dp[i]表示LIS的长度。nums[i]作为LIS的最后一个元素。 for(int j = 0;j < i; j++) { if(nums[i] > nums[j]) { //满足递增 dp[i]=max(dp[i], dp[j] + 1); //利用状态转移方程 } } } int res=0; for(int i = 0;i < n; i++) {
//求得最大的dp[i] res = max(res, dp[i]); } return res; }};

 

  • 使用一个数组h[],其中h[i]表示原数组以arr[i]结尾的最长递增子序列的长度
  • 从i=0到i=n-1过程重复进行n次,求得h=[1,1,2,1,3,2,4,3]。求h[i]的时候,需要考察那些比i小的j,如果arr[i]>arr[j],那么h[i]至少应为h[j]+1,这样对前边的遍历之后即可知道h[i]。
  • h的各个元素求得之后,遍历一遍求最大即可。

      

6.   连续子数组的最大和

 

 

 附加问题:只用加法实现1+2+3+...+n,

(循环、判断语句也不用)

1、利用递归来代替循环结构;

2、利用&&与运算的特性来代替if结构。

int add(int n, int &sum)    {        n && add(n-1, sum);        return (sum += n);    }

 

 

7.    问题一: 位运算实现加法

位的异或运算求'和'的结果一致:

异或 1^1=0 1^0=1 0^0=0

求和 1+1=0 1+0=1 0+0=0

位的与运算求'进位‘的结果一致:

位与 1&1=1 1&0=0 0&0=0

进位 1+1=1 1+0=0 0+0=0

于是我们决定用异或运算和与运算来表示加法。

int add(int a, int b) //递归形式  {      if(b==0) //递归结束条件:如果右加数为0,即不再有进位了,则结束。          return a;      int s = a^b;      int c = (a&b)<<1; //进位左移1位,达到进位的目的。      return add(s, c); //再把'和'和'进位'相加。递归实现。  }

 8.   问题二: 位运算实现减法

   减法其实是用加法来实现的。在ALU中,当我求a-b,其实是求[a-b]补。因为有[a-b]补=[a]补 - [b]补= [a]补+[-b]补。所以我就要先求出-b。求一个数的负的操作是将其连符号位一起取反然后加1。

   于是有办法做减法了:先把减数求负,然后做加法

int negtive(int i)  {      return add(~i, 1);  }  int subtraction(int a, int b) //减法运算:利用求负操作和加法操作  {      return add(a, negtive(b));  }

9.  问题三: 位运算实现乘法

乘法操作时即使用补码也要需要考虑符号位了,所以我要先把符号拿出来单独计算。为了方便,先引入两个工具函数,

int getsign(int i) //取一个数的符号,看是正还是负  {      return (i>>31);  }    int bepositive(int i) //将一个数变为正数,如果本来就是正,则不变;如果是负,则变为相反数。注意对于-2147483648,求负会溢出。  {      if(i>>31)          return negtive(i);      else          return i;  }

循环加法替代乘法。a*b,就是把a累加b次。时间复杂度为O(N)。

int multiply(int a, int b)  {      bool flag = true;      if(getsign(a) == getsign(b)) //积的符号判定          flag = false;        a = bepositive(a);//先把乘数和被乘数变为正数      b = bepositive(b);      int ans = 0;      while(b)      {          ans = add(ans, a);          b = subtraction(b, 1);      }        if(flag)          ans = negtive(ans);      return ans;  }

思路二:

在二进制数上做乘法,如下图:

这一过程就是根据乘数的每一位为0或1时,将被乘数错位的加在积上。时间复杂度为O(logN)。

int multiply(int a, int b)  {      bool flag = true;      if(getsign(a) == getsign(b)) //积的符号判定          flag = false;        a = bepositive(a);      b = bepositive(b);      int ans = 0;      while(b)      {          if(b&1)              ans = add(ans, a);          a = (a<<1); //把a错位加在积上          b = (b>>1); //从最低位开始依次判断b的每一位      }        if(flag)          ans = negtive(ans);      return ans;  }

 

 

72. Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character

b) Delete a character
c) Replace a character

public class Solution {    public int minDistance(String word1, String word2) {        int m = word1.length(), n = word2.length();        int[][] dp = new int[m + 1][n + 1];        // 初始化空字符串的情况        for(int i = 1; i <= m; i++){            dp[i][0] = i;        }        for(int i = 1; i <= n; i++){            dp[0][i] = i;        }        for(int i = 1; i <= m; i++){            for(int j = 1; j <= n; j++){                // 增加操作:str1a变成str2后再加上b,得到str2b 需要的次数                int insertion = dp[i][j-1] + 1;                // 删除操作:str1a删除a后,再由str1变为str2b  需要的次数                int deletion = dp[i-1][j] + 1;                // 替换操作:先由str1变为str2,然后str1a的a替换为b,得到str2b  需要的次数(需要先判断是否相等,相等的话加0,不相等就加1)                int replace = dp[i-1][j-1] + (word1.charAt(i - 1) == word2.charAt(j - 1) ? 0 : 1);                // 三者中取最小的一个操作作为当前的dp                dp[i][j] = Math.min(replace, Math.min(insertion, deletion));               }        }        return dp[m][n];    }}

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/simplepaul/p/7688707.html

你可能感兴趣的文章
PowerDesigner 15生成数据字典
查看>>
App的selenium,Appium爬App!
查看>>
公众号支付相关需要注意的问题
查看>>
字符验证码识别项目记录
查看>>
su 、 sudo 命令及限制 root 远程登录
查看>>
spring cloud微服务分布式云架构-commonservice-config配置服务搭建
查看>>
東方 project 联机版开发日记(1)
查看>>
业务代码解构利器--SWAK
查看>>
20180828 上课截图
查看>>
关于H5跳转到小程序和android的方法
查看>>
rsync通过服务同步、Linux系统日志、screen工具
查看>>
Redis分布式锁的实现原理看这篇就够了~
查看>>
浅谈C++ STL中的优先队列(priority_queue)
查看>>
jenkins 本地二维码生成 高级篇
查看>>
learn ml
查看>>
设计模式-命令模式
查看>>
PyQt5教程(三)——布局管理
查看>>
curl只能抓取页面的部分内容的原因
查看>>
OSChina 周五乱弹 —— 你专业是啥,被叫去搬砖了吗?
查看>>
OSChina 周五乱弹 ——发现办公室女同事走光了
查看>>