Given a list of strings, you could concatenate these strings together into a loop, where for each string you could choose to reverse it or not. Among all the possible loops, you need to find the lexicographically biggest string after cutting the loop, which will make the looped string into a regular one.

Specifically, to find the lexicographically biggest string, you need to experience two phases:

  1. Concatenate all the strings into a loop, where you can reverse some strings or not and connect them in the same order as given.
  2. Cut and make one breakpoint in any place of the loop, which will make the looped string into a regular one starting from the character at the cutpoint.

And your job is to find the lexicographically biggest one among all the possible regular strings.

Example:

Input: "abc", "xyz"
Output: "zyxcba"
Explanation: You can get the looped string "-abcxyz-", "-abczyx-", "-cbaxyz-", "-cbazyx-",
where '-' represents the looped status.
The answer string came from the fourth looped one,
where you could cut from the middle character 'a' and get "zyxcba".

Note:

  1. The input strings will only contain lowercase letters.
  2. The total length of all the strings will not over 1,000.

给定一组字符串,对于每个字符串可以逆序或者不变,将字符串按照原始顺序拼接组成一个字符串,循环每一个字符串拼接它们,可以选择循环中的一个字符串在某一个位置切开。求能得到的字典序最大的字符串。

最终结果一定是从某个字符串在某个地方切开(包括在string[0]之前切开)。其余字符串是否需要reverse则取决于reverse之后其字典序是否会增大,如果增大了就reverse,否则就保持不变,这样才能保证最后的结果是字典序最大的。对于a字符串而言,是否需要反向,以及从哪里切开,均取决于最终形成的字符串头部的字典序大小。

解法:首先将所有的字符串都处理成字典序最大的(反向或者不反向),然后连接起来。接着遍历每个字符串,试图将它以及它的reverse从每个位置切开,并测试形成的regular字符串,一旦发现其字典序大于当前的最大值,则更新当前最大值。最后返回最大值即可。

首先将res初始化为“a”,即为字典序中最小的字符串。而在测试切开位置的过程中,只有在p1[j]或者p2[j]大于res[0]的时候才更新res,这样就可以减少冗余的字符串拼接操作,从而提高运行效率。

第一步,处理原字符串,如果strs[i].reverse > strs[i], 则strs[i] = strs[i].reverse. 可以确保mid string是最优的

第二步,对于一个string array,比如 "abc", "def", "xyz", 先生成一个mid string,mid string没有最后一个string,比如"abcdef". 然后update mid string:

mid = mid.substr(str.length()) + strs[(i+n-1) % n];
这样mid string就变成 defxyz(由abcdef,去掉abc,加上xyz),xyzabc.

然后扫原string array中的每一个string,生成相应的截取result。比如对于abc,我们有mid string = defxyz, 所以组合是:
正序:abc-defxyz, bc-defxyz-a, c-defxyz-ab, defxyz-abc
反序:cba-defxyz, ba-defxyz-c, a-defxyz-cb, defxyz-cba,
然后所有循环中挑出全局最大的.

参考 For every given string, we replace the string with the lexicographically larger string out of the original string and the reversed one. After this, we pick up every new string(chosen as the string on which the cuts will be applied), and apply a cut at all the positions of the currently picked string and form the full concantenated string keeping the rest of the newly formed strings intact. We also reverse the current string and follow the same process. While doing this, we keep a track of the largest lexicographic string found so far.

大厂题:阿里巴巴

Java:

public class Solution {
public String splitLoopedString(String[] strs) {
// 先各自翻转一下
for (int i = 0; i < strs.length; i++) {
String rev = new StringBuilder(strs[i]).reverse().toString();
if (strs[i].compareTo(rev) < 0)
strs[i] = rev;
} String res = "";
// 尝试every str作为那个被cut的
for (int i = 0; i < strs.length; i++) {
String rev = new StringBuilder(strs[i]).reverse().toString();
// 比较其 翻转 和 没翻转
for (String st: new String[] {strs[i], rev}) {
// try every k 作为分界点
for (int k = 0; k < st.length(); k++) {
// 拼接其他strs到t
StringBuilder t = new StringBuilder(st.substring(k));
for (int j = i + 1; j < strs.length; j++)
t.append(strs[j]);
for (int j = 0; j < i; j++)
t.append(strs[j]);
t.append(st.substring(0, k));
// 看t是否最大
if (t.toString().compareTo(res) > 0)
res = t.toString();
}
}
}
return res;
}
}  

Java: DFS

public class Solution {
String res = "";
public String splitLoopedString(String[] strs) {
dfs(strs, "", 0, strs.length);
return res;
}
public void dfs(String[] strs, String s, int i, int n) {
if (i < n) {
dfs(strs, s + strs[i], i + 1, n);
dfs(strs, s + new StringBuffer(strs[i]).reverse().toString(), i + 1, n);
} else {
for (int j = 0; j < s.length(); j++) {
String t = s.substring(j) + s.substring(0, j);
if (t.compareTo(res) > 0)
res = t;
}
}
}
}

Java: BFS

public class Solution {

    public String splitLoopedString(String[] strs) {
Queue < String > queue = new LinkedList < > ();
String res = "";
int i = 0, j = 0;
queue.add("");
while (i < strs.length) {
String t = queue.remove();
queue.add(t + strs[i]);
queue.add(t + new StringBuffer(strs[i]).reverse().toString());
j++;
if (j == 1 << i) {
i++;
j = 0;
}
}
while (!queue.isEmpty()) {
String t = queue.remove();
for (int k = 0; k < t.length(); k++) {
String t1 = t.substring(k) + t.substring(0, k);
if (t1.compareTo(res) > 0)
res = t1;
}
}
return res;
}
}

Java: Optimized Solution 

public class Solution {
public String splitLoopedString(String[] strs) {
for (int i = 0; i < strs.length; i++) {
String rev = new StringBuilder(strs[i]).reverse().toString();
if (strs[i].compareTo(rev) < 0)
strs[i] = rev;
}
String res = "";
for (int i = 0; i < strs.length; i++) {
String rev = new StringBuilder(strs[i]).reverse().toString();
for (String st: new String[] {strs[i], rev}) {
for (int k = 0; k < st.length(); k++) {
StringBuilder t = new StringBuilder(st.substring(k));
for (int j = i + 1; j < strs.length; j++)
t.append(strs[j]);
for (int j = 0; j < i; j++)
t.append(strs[j]);
t.append(st.substring(0, k));
if (t.toString().compareTo(res) > 0)
res = t.toString();
}
}
}
return res;
}
}  

Python:

class Solution(object):
def splitLoopedString(self, strs):
"""
:type strs: List[str]
:rtype: str
"""
strs = [max(s, s[::-1]) for s in strs]
ans = ''
for i, st in enumerate(strs):
left, right = ''.join(strs[:i]), ''.join(strs[i+1:])
for s in (st, st[::-1]):
for j in range(len(s)):
ans = max(ans, s[j:] + right + left + s[:j])
return ans  

C++:

class Solution {
public:
string splitLoopedString(vector<string>& strs) {
if(strs.empty()) return "";
else if(strs.size() == 1) return max(strs[0], string(strs[0].rbegin(), strs[0].rend()));
string all = "";
int n = strs.size();
for(int i=0; i<n; i++){
string temp = string(strs[i].rbegin(), strs[i].rend());
if(temp > strs[i]) strs[i] = temp;
}
for(int i=0; i<n-1; i++){
all += strs[i];
}
string result = all + strs[n-1];
for(int i=0; i<n; i++){
string str = strs[i], rev = string(strs[i].rbegin(), strs[i].rend());
all = all.substr(str.length()) + strs[(i+n-1) % n];
for(int j=0; j<=str.length(); j++){
string s1 = str.substr(j) + all + str.substr(0, j), s2 = rev.substr(j) + all + rev.substr(0, j);
if(s1 >= s2 && s1 > result) result = s1;
else if(s2 >= s1 && s2 > result) result = s2;
}
}
return result;
}
};  

C++:

class Solution {
public:
string splitLoopedString(vector<string>& strs) {
if (strs.empty()) return "";
string s = "", res = "a";
int n = strs.size(), cur = 0;
for (string str : strs) {
string t = string(str.rbegin(), str.rend());
s += str > t ? str : t;
}
for (int i = 0; i < n; ++i) {
string t1 = strs[i], t2 = string(t1.rbegin(), t1.rend());
string mid = s.substr(cur + t1.size()) + s.substr(0, cur);
for (int j = 0; j < strs[i].size(); ++j) {
if (t1[j] >= res[0]) res = max(res, t1.substr(j) + mid + t1.substr(0, j));
if (t2[j] >= res[0]) res = max(res, t2.substr(j) + mid + t2.substr(0, j));
}
cur += strs[i].size();
}
return res;
}
};

  

All LeetCode Questions List 题目汇总

[LeetCode] 555. Split Concatenated Strings 分割串联字符串的更多相关文章

  1. [LeetCode] Split Concatenated Strings 分割串联字符串

    Given a list of strings, you could concatenate these strings together into a loop, where for each st ...

  2. 【LeetCode】555. Split Concatenated Strings 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历 日期 题目地址:https://leetcode ...

  3. LeetCode Split Concatenated Strings

    原题链接在这里:https://leetcode.com/problems/split-concatenated-strings/description/ 题目: Given a list of st ...

  4. [LeetCode] Encode and Decode Strings 加码解码字符串

    Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...

  5. [LeetCode] 249. Group Shifted Strings 分组偏移字符串

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  6. LeetCode OJ:Isomorphic Strings(同构字符串)

    Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...

  7. C语言实现split以某个字符分割一个字符串

    方式一: 使用strtok # include <string.h> # include <stdio.h> void split(char *src,const char * ...

  8. split 将字符串分割成字符串数组

    list_name = list_name.split(","); split() 方法用于把一个字符串分割成字符串数组. 语法 stringObject.split(separa ...

  9. java:字符串的split方法,使用多个分隔符,分割一个字符串

    java语言中,多个分隔符,分割一个字符串: String[] tmpAuthors=tempAuthorStr.split(";|,|:|,"); 可以在线测试:java代码 在 ...

随机推荐

  1. KMP算法的时间复杂度与next数组分析

    一.什么是 KMP 算法 KMP 算法是一种改进的字符串匹配算法,用于判断一个字符串是否是另一个字符串的子串 二.KMP 算法的时间复杂度 O(m+n) 三.Next 数组 - KMP 算法的核心 K ...

  2. mysql类似to_char()to_date()函数mysql日期和字符相互转换方法date_f

    mysql 类似to_char() to_date()函数mysql日期和字符相互转换方法 date_format(date,'%Y-%m-%d') -------------->oracle中 ...

  3. CentOS7.5下SVN服务器备份与恢复

    可以先查看 svnadmin 命令的使用说明 svnadmin --help 1.完全备份和增量备份 查看 svnadmin dump 命令的使用说明 svnadmin dump --help svn ...

  4. 项目Alpha冲刺--9/10

    项目Alpha冲刺--9/10 作业要求 这个作业属于哪个课程 软件工程1916-W(福州大学) 这个作业要求在哪里 项目Alpha冲刺 团队名称 基于云的胜利冲锋队 项目名称 云评:高校学生成绩综合 ...

  5. 浏览器 cookie

    Cookie 保存以下几方面的信息: Cookie的名字 Cookie的值 到期时间 所属域名(默认是当前域名) 生效的路径(默认是当前网址) Set-Cookie: name=value[; exp ...

  6. 性能:Transform层面

    数据处理的并行度 1.BlockRDD的分区数 (1)通过Receiver接受数据的特点决定 (2)也可以自己通过repartition设置 2.ShuffleRDD的分区数 (1)默认的分区数为sp ...

  7. Celery + Redis 的探究

    Celery + Redis 的探究 文本尝试研究,使用 redis 作为 celery 的 broker 时,celery 的交互操作同 redis 中数据记录的关联关系. 不在乎过程的,可以直接看 ...

  8. keras中to_categorical()函数解析

    from keras.utils.np_utils import * # 类别向量定义 b = [0, 1, 2, 3, 4, 5, 6, 7, 8] # 调用to_categorical将b按照9个 ...

  9. JS获取本周、本季度、本月、上月、本年的开始日期、结束日期

    /** * 获取本周.本季度.本月.上月的开始日期.结束日期 */ var now = new Date(); //当前日期  var nowDayOfWeek = now.getDay(); //今 ...

  10. 洛谷P2730 [IOI]魔板 Magic Squares

    题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...