2021秋招网易笔试

力扣214 最短回文串

给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。

示例 1:

输入: “aacecaaa”
输出: “aaacecaaa”

示例 2:

输入: “abcd”
输出: “dcbabcd”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-palindrome
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
把要处理的字符分成回文串和非回文串,再将非回文串逆置加到头部。要注意,已经移动出最长回文串边界的情况,这种情况就需要递归处理了。
代码:

class Solution {
public:
    string shortestPalindrome(string s) {
    int n = s.size();
    int i = 0;
    for (int j = n - 1; j >= 0; j--) {
        if (s[i] == s[j])
            i++;
    }
    if (i == n)
        return s;
    string remain_rev = s.substr(i, n);
    reverse(remain_rev.begin(), remain_rev.end());
    //为什么要递归,因为i可能已经移动出了最长字符串的范围
    return remain_rev + shortestPalindrome(s.substr(0, i)) + s.substr(i);//ababbcefbbaba
    }
};

力扣这个题和网易的C++笔试题第一个类似,只是一个是在前面插入,一个是在后面插入。

给一堆(最多15)有价值的东西,均分给2个人,均分不了的,扔掉,求最小扔掉多少

思路:
参考大佬的代码,暴力解。感觉自己对于DFS的理解还是不够深刻啊
代码:

#include 
using namespace std;
int a[20];
int suffixSum[20];
int n;
int minLoss;
void dfs(int first, int second, int cost, int index)
{
    if (index >= n)
    {
        if (first == second)
            minLoss = min(minLoss, cost);
        return;
    }
    if (first == second)
        minLoss = min(minLoss, suffixSum[index] + cost);
    if (abs(first - second) > suffixSum[index])
        return;
    // 给first,给second,扔掉
    dfs(first + a[index], second, cost, index + 1);
    dfs(first, second + a[index], cost, index + 1);
    dfs(first, second, cost + a[index], index + 1);
}
int main(int argc, char const *argv[])
{
    int t;
    cin >> t;
    while (t--)
    {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
            scanf("%d", &a[i]);
        memset(suffixSum, 0, sizeof(suffixSum));
        for (int i = n - 1; i >= 0; --i)
            suffixSum[i] = suffixSum[i + 1] + a[i];
        minLoss = INT32_MAX;
        dfs(0, 0, 0, 0);
        cout << minLoss << endl;
    }
    return 0;
}

DP解法:

#include 
using namespace std;
#define endl '\n'
typedef long long ll;
typedef pair<ll,ll> P;
const int inf=0xffffffff;

int dp[20][1500005];

int main(){
    int T;scanf("%d",&T);
    while(T--){
        memset(dp,-0x3f,sizeof(dp));
        int n;scanf("%d",&n);
        vector<int>a(n+1);
        int sum=0;
        for(int i=1;i<=n;i++){scanf("%d",&a[i]);sum+=a[i];}
        dp[0][0]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=sum;j++){
                dp[i][j]=dp[i-1][j];
                dp[i][j]=max(dp[i][j],max(dp[i-1][j+a[i]]+a[i],dp[i-1][abs(j-a[i])]+a[i]));
            }
        }
        printf("%d\n",sum-dp[n][0]);
    }
    return 0;
}

n(不超过2000)个人排队买票,第i个人要么单独买票,要么和后面一个人一起买(反过来,就是可以和前面一个人买),单独买花费时间a[i],一起买是b[i],求最短时间,售票员可以回家。开始时间是早上08:00:00 am,输出结束时间。

思路:
参考别人代码
代码:

#include
#include
#include
#include
using namespace std;

int getMinCost(vector<int>a, vector<int>b) {
	vector<int>dp(a.size() + 1);
	dp[1] = a[0];
	for (int i = 2; i < dp.size(); ++i) {
		dp[i] = min(dp[i - 1] + a[i - 1], dp[i - 2] + b[i - 2]);
	}
	return dp.back();
}

string getTime(int cost) {
	int h = 8, m = 0, s = 0;
	s = cost % 60;
	cost /= 60;
	m += cost % 60;
	cost /= 60;
	h += cost % 24;
	bool flag = false;
	if (h > 12) {
		h -= 12;
		flag = true;
	}
	string sh = to_string(h);
	if (sh.size() < 2) sh = "0" + sh;
	string sm = to_string(m);
	if (sm.size() < 2) sm = "0" + sm;
	string ss = to_string(s);
	if (ss.size() < 2) ss = "0" + ss;
	return sh + ":" + sm + ":" + ss + " " + (flag ? "pm" : "am");

}

int main() {
	int m;
	cin >> m;
	while (m-- > 0) {
		int n;
		cin >> n;
		vector<int>a(n);
		vector<int>b(n);
		for (int i = 0; i < n; ++i) cin >> a[i];
		for (int i = 0; i < n - 1; ++i) cin >> b[i];
		int cost = getMinCost(a, b);
		cout << getTime(cost) << endl;
	}
	
}

PS: DP真的是需要多多练习啊

你可能感兴趣的:(力扣算法题)