Isomorphic Strings相同结构的字符串
Given two strings s and t, determine if they are isomorphic.
Two strings are isomorphic if the characters in s can be replaced to get t.
All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.
For example,
Given "egg"
, "add"
, return true.
Given "foo"
, "bar"
, return false.
Given "paper"
, "title"
, return true.
翻译:给定两个字符串s和t,判断是否结构相同。两个字符串相同,则s中的字母可以经过替换得到t。
字符串中的每一个字母的出现都必须被其对应字母替换,同时要保证顺序不变。两个字母不可以映射到同一个字母,但是一个字母各异映射它本身。
思路:使用HashMap的想法,将两个字符串替换成数字表示,出现过的字母按照前一个出现的数字替换,这样可以判断两个结构是否相同。例如
egg和add,e第一次出现,e->0,g第一次出现,g->1,g第二次出现,g->1,则字符串变成011.
add,a第一次出现,a->0,d第一次出现,d->1,d第二次出现,g->1,则字符串变成011.
所以两者结构相同。
代码:
public class Solution {
public boolean isIsomorphic(String s, String t) {
if(s == null || t == null)
return false;
if(s.length() != t.length())
return false;
int a[] = new int[128];
int b[] = new int[128];
for(int i = 0; i < a.length; i++)
{
a[i] = -1;
b[i] = -1;
}
int temp1 = 0;
int temp2 = 0;
StringBuilder sTemp = new StringBuilder();
StringBuilder tTemp = new StringBuilder();
for(int i = 0; i < s.length(); i++)
{
temp1 = s.charAt(i);
temp2 = t.charAt(i);
if(a[temp1] < 0)
{
a[temp1] = i;
}
sTemp.append(a[temp1]);
if(b[temp2] < 0)
{
b[temp2] = i;
}
tTemp.append(b[temp2]);
}
if(sTemp.toString().equals(tTemp.toString()))
return true;
return false;
}
}
Decode Ways计算有多少种译码情况
A message containing letters from A-Z
is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
翻译:一个消息里原本包含从A到Z,使用如下映射关系,被编码为数字
给定一个编码消息包含数字0-9,计算总共有多少种译码情况。
例如:“12”可以被译码为“AB”或“L”
解法:其实一眼下去我想利用递归的想法去解决这个问题,不过觉得不是最好的解决方法,于是乎就想到了一个动态规划的方法,利用“1234”来解释一下这个想法,首先给一个length的一维数组,
对于第一个数字,只有一种情况,就是A;
对于第二个数字,考虑到只单独用2,则是B,如果考虑两个数字结合,那就要结合前一个数,12就变成L,那就有两种情况;
对于第三个数字,和上面想法一样,如果只考虑3,则情况和第二种一样两种,加上结合前一个数的情况,就要加上第一个数那的情况数,则为三种情况;
对于第四个数字,因为和前面的数字结合没有映射结果,所以只考虑单个数字的映射,那么情况和第三个数字的情况一样,三种。
动态规划的式子是:res[i] = res[i-1]+res[i-2]{ 10<s.charAt(i)+s.charAt(i-1) - 2*'0'<27 }
public int numDecodings(String s) {
if(s == null || s.length() == 0)
return 0;
if(s.charAt(0) == '0')
return 0;
if(s.length() == 1 && s.contains("0"))
return 0;
if(s.length() == 1)
return 1;
char[] array = s.toCharArray();
int res[] = new int[array.length];
int temp = 0,preTemp = 0,toal = 0;
res[0] = 1;
for(int i = 1; i < s.length(); i++)
{
temp = array[i] - '1' + 1;
preTemp = array[i - 1] - '1' + 1;
toal = preTemp * 10 + temp;
if(temp > 0)
res[i] += res[i - 1];
if(i > 1 && toal >= 10 && toal <= 26)
res[i] += res[i - 2];
else if(toal >= 10 && toal <= 26)
res[1]++;
}
return res[res.length - 1];
}
Palindrome Partitioning(回文串分隔)
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab"
,
Return
[ ["aa","b"], ["a","a","b"] ]
给定一个字符串,分隔字符,使其中每一组字符都是回文字符,返回所有可能的情况。
分析:利用回溯法进行分析,可以从第一个字符开始
List<List<String>> res = new ArrayList<List<String>>();
public List<List<String>> partition(String s) {
if(s.length() == 0 || s == null)
return res;
backtrack(s, new ArrayList<String>(), 0);
return res;
}
public void backtrack(String s, List<String> list, int index){
if(index == s.length())
{
res.add(new ArrayList<String>(list));
return;
}
for(int i = index + 1; i <= s.length(); i++)
{
if(isPalindrome(s.substring(index,i)))
{
list.add(s.substring(index,i));
backtrack(s, list, i);
list.remove(list.size() - 1);
}
}
}
public boolean isPalindrome(String s){
if(s.length() == 0 || s == null)
return false;
int left =0, right = s.length() - 1;
while(left<right)
{
if(s.charAt(left) == s.charAt(right))
{
left++;
right--;
}else
return false;
}
return true;
}
ZigZag Conversion(循环对角线结构)
The string "PAYPALISHIRING"
is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N A P L S I I G Y I RAnd then read line by line:
"PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3)
should return "PAHNAPLSIIGYIR"
.
翻译:一个字符串用给定的行数用循环对角线结构的形式表示,则变成如下:(你可以以一个更易读的方式展示)
分析:
这就是循环对角线结构,可以以一列多一列少来作为判断的依据,首先,定义一个StringBuffer数组来存储每一行的值,根据输入的值为nRows,则列的数量多为flagLong=nRows,列的数量少的为flagShort=nRows-2,则每次进入一行多的就加入对应的string里,需要注意的一点事关于补空格的问题,因为我是用i%nRows去
算出他的对应数组的序号,所以要补空格才能得出对应的序号。那么每次按照这样的点来取,最后数组里面就存放了循环对角线每一行的值。
代码:
public String convert(String s, int numRows) {
if(s == null || s.length() == 0 || numRows == 0)
return "";
if(numRows == 1 || s.length() <= numRows)
return s;
StringBuffer[] array = new StringBuffer[numRows];
int temp = 0;//对应序号
int flagLong = numRows;
int flagShort = numRows - 2;
int add = 0;
for(int i = 0; i < s.length(); i++)
{
temp = i % numRows;
if(flagLong != 0)
{
flagLong--;
temp = (i + add) % numRows;//补空
flagShort = (flagLong == 0)?(numRows - 2):0;
add = (flagLong == 0)?(add + 2):add;
}else if(flagShort != 0){
temp = flagShort ;
flagShort--;
flagLong = (flagShort == 0)?numRows:0;
}
if(array[temp] == null)
{
array[temp] = new StringBuffer();
}
array[temp].append(s.charAt(i));
}
for(int i = 1; i < numRows; i++)
array[0].append(array[i]);//合并数据
return array[0].toString();
}