选择排序:首先找到最小的那个元素将其与数组的第一个元素进行交换,再次从剩下的元素中找到最小的元素,将其与第二个元素交换,以此类推。选择排序大约需要N~2/2次比较和N次交换。
public class Selections{
public static void sort(int a[]){
int N=a.length;
for(i=0;i<N;i++){
int min=i;
for(j=i+1;i<N;j++){
if (a[min]>a[j]){
min=j;
exchange(a,i,min);
}
}
}
}
public static void exchange(a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
第一个元素先确定为最小,然后和剩下其他的元素比较,那个最小和第一个元素交换,余下类似;
插入排序:类似于抓牌排序
public class Insertion{
public static void sort(int a[]){
int N=a.length;
for(i=1;i<N;i++){
for(j=i-1;j>=0&&(a[j]>a[i]);j++){
exchange(a,i,j);
}
}
}
public static exchange(a,int i,int j){
int temp=a[j];
a[i]=temp;
a[j]=a[i];
}
}
插入排序对几乎有序的排序更有效,而选择排序都是交换和排序。
希尔排序:
public class shell{
public static void sort(int a[]){
int N=a.length;
int h=1;
while(h<N/3){
h=3*h+1;
}
while(h>=1){
for(int i=h;i<N;i++){
for(int j=i;j>=h&&a[j]>a[j-h];j-=h){
exchange(a,j-h,j);
}
h=h/3;
}
}
}
public static exchange(a,i,j){
int temp=a[i];
a[j]=a[i];
a[j]=temp;
}
}
public class Solution{
public int lengthOfLongestSubstring(String s) {
int N=s.length();
int res=0;
for(int start=0;start<N;start++){
for(int end=start+1;end<N;end++){
if(istrue(s,start,end)){
Math.max(res,end-start)
}
}
return res;
}
public boolean istrue(String s,int i,int j){
Set<string> set=new HashSet<string>();
for(;i<j;i++){
if(set.contains(s.indexOf(i))){
boolean req=true;
set.remove(i++);
}else{
req=false;
set.add(s.indexOf(i++)
}
}
return req;
}
}
}
public class Solution{
public int lengthOfLongestSubstring(String s) {
if s.length()==0 ;return 0;
int N=s.length();
int start=0;
int end=0;
int req=0;
Set<String> set=new HashSet<String>();
while(start<N&&end<N){
if(set.contains(s.chatAt(end)){
set.remove(s.chatAt(start++))
}else{
set.add(s.chatAt(end++))
req=Math.max(res,end-start);
}
}
return req;
}
}
public class Solution{
public int lengthOfLongestSubstring(String s) {
int maxLength=0;
if s.length()==0 ;return 0;
List<Character> list=new ArrayList<Character>();
list.add(s.charAt(0));
for(int start=1;i<s.length;start++){
if(list.contains(s.charAt(start))){
int index=list.indexOf(s.chatAt(start));
list=list.subList(index+1,list.size());
list.add(s.chatAt(start));
maxLength=Math.max(maxlenth,list.size());
}else{
list.add(s.chatAt(start));
maxLength=Math.max(maxlenth,list.size());
}
}
return maxlength;
}
}
最短以及最长字符串子串选用滑动窗口法,该算法展示了如何将嵌套for循环在少数问题中转换为单个for循环,从而减少了时间的复杂性。
7
class Solution {
public int reverse(int x) {
int num=0;
int n=0;
int [] a=new int[100];
int flag=0
if (x>0) flag=1;
x=Math.abs(x);
while(x!=0){
a[n++]=x%10;
x=x/10;
}
int ans,t=0;
for(int i=0,i<n;i++){
//t=Math.pow(10,n-1-i);
//num+=a[i]*t;
//if(num/t!=10) return 0;
t=ans;
ans=t*10+a[i];
if(t!=ans/10) return 0;
}
if(flag==0) num=-num;
return num;
}
}
LeetCode 5 最长回文 动态规划:
class Solution {
public String longestPalindrome(String s) {
boolean[][] flag = new boolean[s.length()][s.length()];
int begin = 0;
int end = 0;
int maxlen = 0;
for (int i = s.length(); i >= 0; i--) {
for (int j = i; j < s.length(); j++) {
if (s.charAt(i)==s.charAt(j) && (j-i <= 2 || flag[i+1][j-1])){
flag[i][j] = true;
if (maxlen < j-i+1){
maxlen = j-i+1;
begin = i;
end = j;
}
}
}
}
if(s.length()>0){
return s.substring(begin,end+1);
}else{
return s;
}
}
}
中心扩展法:
class Solution {
public String longestPalindrome(String s) {
int begin = 0;
int end = 0;
int maxlen = 0;
//类似于aba这种结构,指的是子串,并不是字符串
for (int i = 0; i< s.length(); i++) {
int j=i-1;
int k=i+1;
while(j>=0&&k<s.length()&&s.charAt(j)==s.charAt(k)){
if (maxlen < k-j+1){
maxlen = k-j+1;
begin = k;
end = j;
}
j--;
k++;
}
}
for (int i = 0; i<s.length(); i++) {
int j=i;
int k=i+1;
while(j>=0&&k<s.length()&&s.charAt(j)==s.charAt(k)){
if (maxlen < k-j+1){
maxlen = k-j+1;
begin = k;
end = j;
}
j--;
k++;
}
}
if(maxlen>0){
return s.substring(begin,end+1);
}else if(s.length()>0){
return s.substring(s.length()-1,s.length());
}else{
return s;
}
}
}
class Solution {
String longest = "";
public String longestPalindrome(String s) {
for(int i = 0; i < s.length(); i++){
helper(s, i, 0);
helper(s, i, 1);
}
return longest;
}
private void helper(String s, int idx, int offset){
int left = idx;
int right = idx + offset;
while(left>=0 && right<s.length() && s.charAt(left)==s.charAt(right)){
left--;
right++;
}
String currLongest = s.substring(left + 1, right);
if(currLongest.length() > longest.length()){
longest = currLongest;
}
}
}
leetcode 4
here are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
两个排好序的的数组找中位数,时间复杂度要求 O(log (m+n)).
如果把两个数组合并,排序再找中位数,显然时间复杂度是O(nlogn).
问题转换为求两个数组中第K个小的元素.参考http://blog.csdn.net/yutianzuijin/article/details/11499917/
首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、<和=。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。
当A[k/2-1]>B[k/2-1]时存在类似的结论。
当A[k/2-1]=B[k/2-1]时,我们已经找到了第k小的数,也即这个相等的元素.
- 如果A或者B为空,则直接返回B[k-1]或者A[k-1];
- 如果k为1,我们只需要返回A[0]和B[0]中的较小值;
- 如果A[k/2-1]=B[k/2-1],返回其中一个;
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int a=nums1.length;
int b=nums2.length;
int totalnums=a+b;
if(totalnums%2==1){
return findKth(nums1,0,a,nums2,0,b,totalnums/2+1);
}else{
return(findKth(nums1,0,a,nums2,0,b,totalnums/2)+findKth(nums1,0,a,nums2,0,b,totalnums/2))/2;
}
}
public static double findKth(int nums1[],int abegin,int a,int nums2[],int bbegin,int b,int k){
if(a>b) return findKth(nums2,bbegin,b,nums1,abegin, a,k);
if(k==1) return Math.min(nums1[abegin],nums2[bbegin]);
if(a==0) return nums2[abegin+k-1];
int ma=Math.min(k/2,a);int mb=k-ma;
if(nums1[abegin+ma-1]<nums2[bbegin+mb-1])
return findKth(nums1,abegin+ma,a-ma,nums2,bbegin,b,k-ma);
else if(nums1[abegin+ma-1]>nums2[bbegin+mb-1])
return findKth(nums1,abegin,a,nums2,bbegin+mb,b-mb,k-mb);
else return nums2[bbegin+mb+1];
}
}
LeetCode 13 数字变成罗马数
class Solution {
public int romanToInt(String s) {
if(s==null||s.length()<1) return -1;
char []ch=s.toCharArray();
HashSet<Character,Integer> hash=new HashSet<Character,Integer>();
hash.put('M',1000);
hash.put('D',500);
hash.put('C',100);
hash.put('L',50);
hash.put('X',10);
hash.put('V',5);
hash.put('I',1);
int res=0;//总和
int temp=0;//上一次的值
int value=0;//这次的值
for(int i=ch.length-1;i>=0;i--){
value=hash.get(ch[i]);
if(temp<=value){
res+=value;
temp=value;
}esle{
res-=value;
temp=value;
}
return res;
}
}
LeetCode 2 两个数相加
估计是学会使用链表
/**
* 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 headNode = new ListNode(0);
ListNode currentNode = headNode;
int carray = 0;
while(l1 != null || l2 != null){
if(l1!=null){
carray +=l1.val;
l1 = l1.next;
}
if(l2!=null){
carray +=l2.val;
l2 = l2.next;
}
currentNode.next = new ListNode(carray%10);
currentNode = currentNode.next;
carray/=10;
}
if(carray==1){
currentNode.next = new ListNode(1);
currentNode = currentNode.next;
}
return headNode.next;
}
}
13水桶问题:装最多的水
class Solution {
public int maxArea(int[] height) {
int l=0;
int r=height.length;
int contain=0;
while(l<r){
int high=Math.min(height[l],height[r]);
contain=Math.max(contain,(r-l)*high);
while(height[l]<=high&&l<r) l++;
while(height[r]<=high&&l<r) r--;
}
return contain;
}
}
class Solution {
public int maxArea(int[] height) {
int N=height.length;
int contain=0;
int temp=0;
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
temp=(j-i)*Math.min(height[i],height[j]);
contain=Math.max(contain,temp);
}
}
return contain;
}
}
}
LeetCode12 Integer to Roman
class Solution {
public String intToRoman(int num) {
String [] m={"","M","MM","MMM"};
String [] c={"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
String [] x={"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
String [] i={"","I","II","III","IV","V","VI","VII","VIII","IX"};
return m[num/1000]+c[num%1000/100]+x[num%100/10]+i[num%10];
}
}
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
class Solution {
public String intToRoman(int num) {
String [] str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
int [] nums={1000,900,500,400,100,90,50,40,10,9,5,4,1};
StringBuilder strbuilder=new StringBuilder();
for(int i=0;i<nums.length;i++){
int count=num/nums[i];
while(count!=0){
strbuilder.append(str[i]);
count--;
}
num=num%nums[i];
}
return strbuilder.toString();
}
}
leetcode 3sum
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
if(nums==null||nums.length<=2) return res;
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
if(nums[i]>0) break;
if(i>0&&nums[i]==nums[i-1]) {continue;}
int left=i+1; int right=nums.length-1;
int sum=-nums[i];
while(left<right){
if(nums[left]+nums[right]==sum){
ArrayList<Integer> triplet = new ArrayList<>();
triplet.add(nums[left]);
triplet.add(nums[right]);
triplet.add(nums[i]);
res.add(triplet);
while(left<right&&nums[left++]==nums[left]){}
while(left<right&&nums[right--]==nums[right]){}
}else if(nums[left]+nums[right]<sum){
while(left<right&&nums[left++]==nums[left]){}
}else{
while(left<right&&nums[right--]==nums[right]){}
}
}
}
return res;
}
}
先对列表进行排序,然后从头到尾遍历。这样每次都固定住一个值,而不是用双指针来解决三值问题,好像是可行的。
在固定一个值之后,剩下的有序列表中,用双指针法寻找两个值的和是否是固定值的负数。这样指针移动的标准也就出来了。如下图:
当两值之和大于固定值的负数时,右边的指针左移
当两值之和小于固定值的负数时,左边指针右移
当两值之和恰好为固定值负数,保存结果。此时有个很有必要的操作:判断 start+1的值,end-1的值,是否与上一个一样,相同的话,则跳过处理
leetcode 10 正则表达式的匹配
class Solution {
public boolean isMatch(String s, String p) {
boolean [][] rex=new boolean[s.length()+1][p.length()+1];
for(int i=0;i<s.length()+1;i++){
for(int j=0;j<p.length()+1;j++){
rex[i][j]=false;
}
}
rex[0][0]=true;
for(int i=0;i<=s.length();i++){
for(int j=1;j<=p.length();j++){
if(i > 0 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.')){
rex[i][j]=rex[i-1][j-1];
}
if(p.charAt(j-1)=='*'){
if(i==0||(s.charAt(i-1)!=p.charAt(j-2)&&p.charAt(j-2)!='.')){
rex[i][j]=rex[i][j-2];
}else{
rex[i][j]=rex[i-1][j]||rex[i][j-1]||rex[i][j-2];
}
}
}
}
return rex[s.length()][p.length()];
}
}