(注:每一条目中第一种为C/C++的题解,第二种为Java的题解)
1 两数之和(Two Sum)
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target)
{
int *res = (int*)malloc(sizeof(int)*2);
for(int i = 0;i < numsSize-1;i++)
{
for(int j = i+1;j < numsSize;j++)
{
if(nums[i]+nums[j] == target)
{
res[0] = i;
res[1] = j;
return res;
}
}
}
return res;
}
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();
int[] res = new int[2];
for(int i = 0;i < nums.length;i ++)
{
m.put(nums[i], i);
}
for(int i = 0;i < nums.length;i ++)
{
int t = target - nums[i];
if(m.containsKey(t) && m.get(t) != i)
{
res[0] = i;
res[1] = m.get(t);
break;
}
}
return res;
}
}
2. 两数相加
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
{
struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode)),*tail = head;//建立空的头结点
int carry = 0;
for(;l1 && l2;l1 = l1->next,l2 = l2->next)
{
int sum = l1->val + l2->val + carry;
if(sum > 9)
{
sum -= 10;
carry = 1;
}
else
{
carry = 0;
}
tail->next = (struct ListNode*)malloc(sizeof(struct ListNode));
tail = tail->next;
tail->val = sum;
}
//取两个链表较长的一个剩余部分
l1 = l1 ? l1 : l2;
for(;l1;l1 = l1->next)
{
int sum = l1->val + carry;
if(sum > 9)
{
sum -= 10;
carry = 1;
}
else
{
carry = 0;
}
tail->next = (struct ListNode*)malloc(sizeof(struct ListNode));
tail = tail->next;
tail->val = sum;
}
//如果还有进位,再分配一个节点
if(carry)
{
tail->next = (struct ListNode*)malloc(sizeof(struct ListNode));
tail = tail->next;
tail->val = 1;
}
//链表指向空节点,即结束
tail->next = NULL;
//将空的头结点释放,从第二个节点返回
tail = head;
head = head->next;
//c语言注意释放
free(tail);
return head;
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode l3 = new ListNode(0);
ListNode result = l3;
int carry = 0;
while(l1 != null || l2 != null) //l1与l2有一个不为空,则在他们结尾处补0,而后逐位相加即可
{
int a = l1 == null ? 0 : l1.val;
int b = l2 == null ? 0 : l2.val;
if(a + b + carry <= 9)
{
result.next = new ListNode(a + b + carry);
carry = 0;
}
else
{
result.next = new ListNode((a + b + carry) % 10);
carry = 1;
}
result = result.next;
if(l1 != null)
{
l1 = l1.next;
}
if(l2 != null)
{
l2 = l2.next;
}
}
if(carry == 1) //不要忘记两个数的最高位相加之后有可能会有进位,需要将此进位计算在内
{
result.next = new ListNode(carry);
}
return l3.next; /*此处l3的链表形式为l3->result,所以当返回l3.next时,才能输出正确答案[7,0,8],此处要是返回l3,则输出的是[0,7,0,8];要是返回的result,则输出的是result指向的当前节点值[8];要是返回的是result.next,则输出的是result当前节点的下一个节点值[]*/
}
}
3. 无重复字符的最长子串
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
/*这里建立一个256位大小的整型数组来代替HashMap,这样做的原因是ASCII表共能表示256个字符,所以可以记录所有字符,然后我们需要定义两个变量res和left,其中res用来记录最长无重复子串的长度,left指向该无重复子串左边的起始位置,然后我们遍历整个字符串,对于每一个遍历到的字符,如果哈希表中该字符串对应的值为0,说明没有遇到过该字符,则此时计算最长无重复子串,i - left +1,其中i是最长无重复子串最右边的位置,left是最左边的位置,还有一 种情况也需要计算最长无重复子串,就是当哈希表中的值小于left,这是由于此时出现过重复的字符,left的位置更新了,如果又遇到了新的字符,就要重新计算 最长无重复子串。最后每次都要在哈希表中将当前字符对应的值赋值为i+1。*/
int m[256] = {0}, res = 0, left = 0;
for (int i = 0; i < s.size(); ++i) //string类型的变量不可以用strlen()直接获取其长度,需要使用s.size()或者strlen(s.c_str())
{
if (m[s[i]] == 0 || m[s[i]] < left )
{
res = max(res, i - left + 1);
}
else
{
left = m[s[i]];
}
m[s[i]] = i + 1;
}
return res;
}
};
class Solution {
public int lengthOfLongestSubstring(String s) {
int result = 0;
HashMap<Character, Integer> res = new HashMap<Character, Integer>();
for(int start = 0, end = 0;end < s.length();end ++)
{
char tmp = s.charAt(end);
if(res.containsKey(tmp))
{
start = Math.max(res.get(tmp), start);
}
result = Math.max(end - start + 1, result);
res.put(s.charAt(end), end + 1);
}
return result;
}
}
5. 最长回文子串
class Solution {
public:
string longestPalindrome(string s)
{
/*动态规划的方法
int dp[s.size()][s.size()] = {0};
int left,right,len = 0;
for (int i = 0; i < s.size(); ++i) {
for (int j = 0; j < i; ++j) {
dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
if (dp[j][i] && len < i - j + 1) {
len = i - j + 1;
left = j;
right = i;
}
}
dp[i][i] = 1;
}
return s.substr(left, right - left + 1);*/
//马拉车算法(待深入理解)
string t ="$#";
for (int i = 0; i < s.size(); ++i) {
t += s[i];
t += '#';
}
int p[t.size()] = {0}, id = 0, mx = 0, resId = 0, resMx = 0;
for (int i = 0; i < t.size(); ++i) {
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (t[i + p[i]] == t[i - p[i]]) ++p[i];
if (mx < i + p[i]) {
mx = i + p[i];
id = i;
}
if (resMx < p[i]) {
resMx = p[i];
resId = i;
}
}
return s.substr((resId - resMx) / 2, resMx - 1);
}
};
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
}
6. Z 字形变换
class Solution {
public:
string convert(string s, int numRows)
{
if(numRows <= 1)
{
return s;
}
string res = "";
int size = 2 * numRows - 2;
for(int i = 0;i < numRows;i ++)
{
for(int j = i;j < s.size();j +=size)
{
res += s[j];
int temp = j + size - 2 * i;
if(i != 0 && i != numRows - 1 && temp < s.size())
{
res += s[temp];
}
}
}
return res;
}
};
class Solution {
public String convert(String s, int numRows) {
if (numRows == 1) return s;
StringBuilder ret = new StringBuilder();
int n = s.length();
int cycleLen = 2 * numRows - 2;
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j + i < n; j += cycleLen)
{
ret.append(s.charAt(j + i));
if (i != 0 && i != numRows - 1 && j + cycleLen - i < n)
ret.append(s.charAt(j + cycleLen - i));
}
}
return ret.toString();
}
}
7. 整数反转
class Solution {
public:
int reverse(int x)
{
long long res = 0;
while (x)
{
res = 10 * res + x % 10;
x /= 10;
}
return (res > INT_MAX || res < INT_MIN) ? 0 : res;
}
};
class Solution {
public int reverse(int x) {
long temp=0;
while(x!=0){
temp*=10;
temp+=x%10;
x/=10;
}
if(temp<Integer.MIN_VALUE || temp>Integer.MAX_VALUE)
return 0;
return (int)temp;
}
}
8. 字符串转换整数 (atoi)
class Solution {
public:
int myAtoi(string str)
{
if (str.empty())
{
return 0;
}
int sign = 1, base = 0, i = 0, n = str.size();
while (i < n && str[i] == ' ')
{
++i;
}
if (str[i] == '+' || str[i] == '-')
{
sign = (str[i++] == '+') ? 1 : -1;
}
while (i < n && str[i] >= '0' && str[i] <= '9')
{
if (base > INT_MAX / 10 || (base == INT_MAX / 10 && str[i] - '0' > 7))
{
return (sign == 1) ? INT_MAX : INT_MIN;
}
base = 10 * base + (str[i++] - '0');
}
return base * sign;
}
};
class Solution {
public int myAtoi(String str) {
str = str.trim();
if (str == null || str.length() == 0)
return 0;
char firstChar = str.charAt(0);
int sign = 1;
int start = 0;
long res = 0;
if (firstChar == '+') {
sign = 1;
start++;
} else if (firstChar == '-') {
sign = -1;
start++;
}
for (int i = start; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return (int) res * sign;
}
res = res * 10 + str.charAt(i) - '0';
if (sign == 1 && res > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
if (sign == -1 && res > Integer.MAX_VALUE)
return Integer.MIN_VALUE;
}
return (int) res * sign;
}
}
9. 回文数
bool isPalindrome(int x)
{
int reverse = 0;
int back = x;
if(x == 0)
return true;
if(x < 0 || x % 10 == 0)
return false;
while(x)
{
reverse = reverse * 10 + x % 10;
x /= 10;
}
return back == reverse;
}
class Solution {
public boolean isPalindrome(int x) {
int res = 0;
int tmp = x;
if(x < 0)
{
return false;
}
while(x != 0)
{
res = res*10 + x%10;
x /= 10;
}
return res == tmp ? true : false;
}
}
11. 盛最多水的容器
class Solution {
public:
int maxArea(vector<int>& height)
{
int water = 0;
int max_water = 0;
for(int i = 0;i < height.size();i ++)
{
for(int j = i;j < height.size();j ++)
{
water = (j - i)*min(height[i],height[j]);
max_water = max(water,max_water);
}
}
return max_water;
}
};
class Solution {
/*暴力法
public int maxArea(int[] height) {
int water = 0;
int max_water = 0;
for(int i = 0;i < height.length;i ++)
{
for(int j = i;j < height.length;j ++)
{
water = (j - i) * Math.min(height[i], height[j]);
max_water = Math.max(water, max_water);
}
}
return max_water;
}*/
/*双指针法*/
public int maxArea(int[] height) {
int maxarea = 0, l = 0, r = height.length - 1;
while (l < r) {
maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
if (height[l] < height[r])
l++;
else
r--;
}
return maxarea;
}
}
13. 罗马数字转整数
int romanToInt(char* s)
{
char *input = s;
int output = 0;
int i = 0;
while(i < strlen(input))
{
if(input[i] == 'I')
{
if(input[i+1] == 'V')
{
output += 4;
i += 2;
}
else if (input[i+1] == 'X')
{
output += 9;
i += 2;
}
else
{
output += 1;
i += 1;
}
}
if(input[i] == 'X')
{
if(input[i+1] == 'L')
{
output += 40;
i += 2;
}
else if (input[i+1] == 'C')
{
output += 90;
i += 2;
}
else
{
output += 10;
i += 1;
}
}
if(input[i] == 'C')
{
if(input[i+1] == 'D')
{
output += 400;
i += 2;
}
else if (input[i+1] == 'M')
{
output += 900;
i += 2;
}
else
{
output += 100;
i += 1;
}
}
if(input[i] == 'V')
{
output += 5;
i += 1;
}
if(input[i] == 'L')
{
output += 50;
i += 1;
}
if(input[i] == 'D')
{
output += 500;
i += 1;
}
if(input[i] == 'M')
{
output += 1000;
i += 1;
}
}
return output;
}
class Solution {
public int romanToInt(String s) {
int res = 0;
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("I", 1);
map.put("IV", 4);
map.put("V", 5);
map.put("IX", 9);
map.put("X", 10);
map.put("XL", 40);
map.put("L", 50);
map.put("XC", 90);
map.put("C", 100);
map.put("CD", 400);
map.put("D", 500);
map.put("CM", 900);
map.put("M", 1000);
for(int i = 0;i < s.length();)
{
if(i + 1 < s.length() && map.containsKey(s.substring(i, i+2)))
{
res += map.get(s.substring(i, i+2));
i +=2;
}
else
{
res += map.get(s.substring(i, i+1));
i ++;
}
}
return res;
}
}
14. 最长公共前缀
class Solution {
public:
string longestCommonPrefix(vector<string>& strs)
{
if(strs.empty())
{
return "";
}
string res = "";
for(int i = 0;i < strs[0].size();i ++)
{
char c = strs[0][i];
for(int j = 1;j < strs.size();j ++)
{
if(strs[j][i] != c || i >= strs[i].size())
{
return res;
}
}
res.push_back(c);
}
return res;
}
};
class Solution {
public String longestCommonPrefix(String[] strs) {
if(strs.length == 0)
{
return "";
}
String res = strs[0];
for(int i = 1;i < strs.length;i ++)
{
int j = 0;
for(;j < res.length() && j < strs[i].length();j ++)
{
if(res.charAt(j) != strs[i].charAt(j))
{
break;
}
}
res = res.substring(0, j);
}
return res;
}
}
20. 有效的括号
class Solution {
public:
bool isValid(string s)
{
stack<char> kuohao;
for(int i = 0;i < s.size();i ++)
{
if(s[i] == '(' || s[i] == '[' || s[i] == '{')
{
kuohao.push(s[i]);
}
else
{
if(kuohao.empty())
{
return false;
}
if(s[i] == ')' && kuohao.top() != '(')
{
return false;
}
if(s[i] == ']' && kuohao.top() != '[')
{
return false;
}
if(s[i] == '}' && kuohao.top() != '{')
{
return false;
}
kuohao.pop();
}
}
return kuohao.empty();
}
};
class Solution {
public boolean isValid(String s) {
while(s.contains("()") || s.contains("[]") || s.contains("{}"))
{
if(s.contains("()"))
{
s = s.replace("()", "");
}
if(s.contains("[]"))
{
s = s.replace("[]", "");
}
if(s.contains("{}"))
{
s = s.replace("{}", "");
}
}
return s.isEmpty();
}
}
21. 合并两个有序链表
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
ListNode *dummy = new ListNode(-1), *cur = dummy;
while (l1 && l2) {
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = l1 ? l1 : l2;
return dummy->next;
}
};
/*递归*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null)
{
return l2;
}
if(l2 == null)
{
return l1;
}
if(l1.val < l2.val)
{
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}
else
{
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
26. 删除排序数组中的重复项
class Solution {
public:
int removeDuplicates(vector<int>& nums)
{
int pre = 0;
if(nums.empty())
{
return 0;
}
for(int i = 0;i < nums.size() - 1;i ++)
{
if (nums[i] != nums[i + 1])
{
nums[++pre] = nums[i + 1];
}
}
return pre + 1;
}
};
class Solution {
public int removeDuplicates(int[] nums) {
int count = 0;
for(int i = 0;i < nums.length - 1;i ++)
{
if(nums[i] != nums[i + 1])
{
/*不需要考虑数组中超出新长度后面的元素*/
nums[++count] = nums[i + 1];
}
}
return count + 1;
}
}
27 移除元素
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int count = 0;
for(int i = 0;i < nums.size();i ++)
{
if(nums[i] != val)
{
nums[count++] = nums[i];
}
}
return count;
}
};
class Solution {
public int removeElement(int[] nums, int val) {
int count = 0;
for(int i = 0;i < nums.length;i ++)
{
if(nums[i] != val)
{
nums[count++] = nums[i];
}
}
return count;
}
}
28. 实现 strStr()
class Solution {
public:
int strStr(string haystack, string needle)
{
int i,j = 0;
if(needle.empty())
{
return 0;
}
if(haystack.size() < needle.size())
{
return -1;
}
for(i = 0;i < haystack.size();i ++)
{
for(j = 0;j < needle.size();j ++)
{
if(haystack[i + j] != needle[j])
{
break;
}
}
if(j == needle.size())
{
return i;
}
}
return -1;
}
};
class Solution {
public int strStr(String haystack, String needle) {
int res = -1;
int len = needle.length();
int lenhay = haystack.length();
if ( lenhay < len )
return -1;
int star = 0 ;
int end = len-1;
while (end < lenhay){
if (haystack.substring(star,end+1).equals(needle)){
return star;
}
end++;
star++;
}
return -1;
}
}
35. 搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target)
{
if(target < nums[0])
{
return 0;
}
if(target > nums[nums.size() - 1])
{
return nums.size();
}
for(int i = 0;i < nums.size();i ++)
{
if(target - nums[i] == 0)
{
return i;
}
else if(target - nums[i] > 0 && target - nums[i + 1] < 0)
{
return i + 1;
}
}
}
};
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length;
while(left < right)
{
int mid = (left + right) / 2;
if(target > nums[mid])
{
left = mid + 1;
}
else if(target < nums[mid])
{
right = mid;
}
else
{
return mid;
}
}
return right;
38. 报数
class Solution {
public:
string countAndSay(int n)
{
if(n <= 0)
{
return "";
}
string res = "1";
while(--n)
{
string cur = "";
for(int i = 0;i < res.size();i ++)
{
int cnt = 1;
while(i + 1 < res.size() && res[i] == res[i + 1])
{
cnt ++;
i ++;
}
cur += to_string(cnt) + res[i];
}
res = cur;
}
return res;
}
};
class Solution {
public String countAndSay(int n) {
if (n <= 0) {
return "";
}
String[] seq = new String[n];
seq[0] = "1";
for (int i = 1; i < n; i++) {
seq[i] = convert(seq[i - 1]);
}
return seq[n - 1];
}
public String convert(String str) {
StringBuilder ans = new StringBuilder();
int count = 1;
for (int i = 0; i < str.length(); i++) {
// 这一部分是"count", 记录连续出现x个y
if (i < str.length() - 1 && str.charAt(i) == str.charAt(i + 1)) {
count++;
} else {
// 这一部分是"say",将上面"count"的结果"xy"作为下一个数的一部分(若上面记录到2个1,就拼接"21")
ans.append(count).append(str.charAt(i));
count = 1;
}
}
return new String(ans);
}
}