算法分析与设计课程作业第十二周#1#2#3#4

来源:互联网 发布:网络机顶盒链接显示器 编辑:程序博客网 时间:2024/05/22 00:19

算法分析与设计课程作业第十二周#1#2#3#4

这周从dynamic programming标签的题目中挑了4道medium题目来做。

338.Counting Bits

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1’s in their binary representation and return them as an array.
Example:
For num = 5 you should return [0,1,1,2,1,2].
Follow up:
It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
Space complexity should be O(n).
Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.

思路

这道题要求了线性时间复杂度与线性空间复杂度。可用动态规划的思想,对某个数二进制形式1的个数,可由前面已经计算了的某个数的1的个数计算得出(这个计算要求O(1)的时间复杂度)。这样整体的时间复杂度为O(n)。
状态转移式:bits[i]:数i二进制形式1的个数
bits[0]=0;
bits[1]=1;
bits[i]=bits[i/2] + i%2;

代码

class Solution {public:    vector<int> countBits(int num) {        vector<int> bits;        bits.push_back(0);        if(num == 0) return bits;        bits.push_back(1);        if(num == 1) return bits;        for(int i = 2; i <= num; i++){            bits.push_back(bits[i/2] + i%2);        }        return bits;    }};

647. Palindromic Substrings

Given a string, your task is to count how many palindromic substrings in this string.
The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
Example 1:
Input: “abc”
Output: 3
Explanation: Three palindromic strings: “a”, “b”, “c”.

Example 2:
Input: “aaa”
Output: 6
Explanation: Six palindromic strings: “a”, “a”, “a”, “aa”, “aa”, “aaa”.

Note:
The input string length won’t exceed 1000.

思路

题目要求的是一个字符串中回文子串的数目。我想到的是穷举字符串中所有子串,每个判断是否为回文子串。要想在O(1)时间内判断出一个子串是否为回文子串(即判断时间不由子串长度决定),就要用到线性规划的思想,也要注意选择子串进行判断的顺序(以下说明怎么确定顺序)。
首先给出状态转移式:bool dp[i][j]:从第i到第j个字符组成的子串是否为回文子串。初始为false。
dp[i][j] = (s[i] == s[j]) && ((j - i <= 1)||dp[i+1][j-1]);
从dp[i][j]需由dp[i+1][j-1]算出,可知计算的外循环要么就是i从大到小,要么就是j从小到大,内循环的计算顺序倒是不要紧。同时要注意i小于等于j。

外循环i从大到小代码

class Solution {public:    int countSubstrings(string s) {        int size = s.size();        int num = 0;        bool dp[size][size];        for(int i = 0; i < size; i++){            for(int j = 0; j < size; j++){                dp[i][j] = false;            }        }        for(int i = size-1; i >= 0; i--){            for(int j = i; j < size; j++){                dp[i][j] = (s[i] == s[j]) && ((j - i  <= 1)||dp[i+1][j-1]);                if(dp[i][j]) num++;            }        }        return num;    }};

外循环j从小到大代码

class Solution {public:    int countSubstrings(string s) {        int size = s.size();        int num = 0;        bool dp[size][size];        for(int i = 0; i < size; i++){            for(int j = 0; j < size; j++){                dp[i][j] = false;            }        }        for(int j = 0; j < size; j++){            for(int i = 0; i <= j; i++){                dp[i][j] = (s[i] == s[j]) && ((j - i  <= 1)||dp[i+1][j-1]);                if(dp[i][j]) num++;            }        }        return num;    }};

413. Arithmetic Slices

A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.
For example, these are arithmetic sequence:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
The following sequence is not arithmetic.
1, 1, 2, 5, 7

A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.
A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], …, A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q.
The function should return the number of arithmetic slices in the array A.

Example:
A = [1, 2, 3, 4]

return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.

思路

这道题求的是一个数组中等差子数组的个数,咋眼一看,跟求回文串那题一样,可以写出极为类似的代码解决问题。这样的代码时间复杂度与空间复杂度为O(n^2),对大数组容易超时。
以下为超时代码。

class Solution {public:    int numberOfArithmeticSlices(vector<int>& A) {        int size = A.size();        if(size < 3) return 0;        int num = 0;        bool dp[size][size];        for(int i = 0; i < size; i++){            for(int j = 0; j < size; j++){                dp[i][j] = false;            }        }        for(int j = 2; j < size; j++){            for(int i = 0; i <= j-1; i++){                dp[i][j] = (A[i+1] - A[i] == A[j] - A[j-1]) && ((j-i <= 2)||dp[i+1][j-1]);                if(dp[i][j] &&j-i >= 2) num++;            }        }        return num;    }};

应有更快捷的方法,可以另辟蹊径。
一个数列到某个数,该数是否为某个等差子数列结尾(或者说为多少个等差子数列的结尾),可以向前看两个数,如果构成等差数列,那这个等差数列的差就确定了,从而可以与前一个数是否为多少个等差子数列结尾构成关系(回文串无法确立这一个关系,关键在于等差数列的等差性质)。
状态转移式:dp[i]:以i结尾有多少个等差子数列//事实上这个储存的信息也比一个布尔值数组多
所求:所有dp[i]的和
dp[0]=0;
dp[1]=0;
if(A[i]-A[i-1] == A[i-1]-A[i-2]) dp[i] = dp[i-1]+1;
else dp[i] = 0;

代码

class Solution {public:    int numberOfArithmeticSlices(vector<int>& A) {        int size = A.size();        if(size < 3) return 0;        int num = 0;        int dp[size];        dp[0] = 0;        dp[1] = 0;        for(int i = 2; i < size; i++){            if(A[i]-A[i-1] == A[i-1]-A[i-2]){                dp[i] = dp[i-1]+1;            }            else                dp[i] = 0;            num += dp[i];        }        return num;    }};

646. Maximum Length of Pair Chain

You are given n pairs of numbers. In every pair, the first number is always smaller than the second number.
Now, we define a pair (c, d) can follow another pair (a, b) if and only if b < c. Chain of pairs can be formed in this fashion.
Given a set of pairs, find the length longest chain which can be formed. You needn’t use up all the given pairs. You can select pairs in any order.
Example 1:
Input: [[1,2], [2,3], [3,4]]
Output: 2
Explanation: The longest chain is [1,2] -> [3,4]

Note:
The number of given pairs will be in the range [1, 1000].

思路

这道题我没有用动态规划的思路,而是用了贪心算法。就是按pair第二个值大小先排好序,然后每次选满足条件的pair第二个值最小的pair构成链条,以让下次选择的空间尽量大,从而可求出链条的最大长度。

代码

class Solution {public:    int findLongestChain(vector<vector<int>>& pairs) {        sort(pairs.begin(), pairs.end(), cmp);        int size = pairs.size();        int num = 1;        int j = 0;        for(int i = 1; i < size; i++){            if(pairs[i][0] > pairs[j][1]){                num++;                j = i;            }        }        return num;    }    static bool cmp(vector<int>& a, vector<int>&b) {        return a[1] < b[1];    }};
阅读全文
1 0
原创粉丝点击