部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

LintCode--【问题记录】

给出一个数组,将这个数组排序,使得所有的奇数在偶数前面,注意奇数之间、偶数之间的相对顺序不变

方法1:新建一个list 存放偶数,将数组中的奇数直接放在前面,然后把list中的偶数添加到数组后面 

时间复杂度O(n) 空间复杂度O(n) 

public void reorder(int[] arr) {
    int len = arr.length;
    List<Integer> list = new ArrayList<Integer>();
    int curri = 0;
    for (int i = 0; i < len; i++) {
        if (arr[i] % 2 == 0) {
            list.add(arr[i]);
        } else {
            arr[curri] = arr[i];
            curri++;
        }
    }
    int j = 0;
    for (int i = curri; i < len; i++) {
        arr[i] = list.get(j);
        j++;
    }
} 

方法2:类似于冒泡排序,相邻两个数,如果前面为偶数后面为奇数,就交换

时间复杂度O(n*n) 空间复杂度O(1)

public static void reOrder3(int[] arr){
    int len = arr.length;
    for(int i = 0 ; i < len ; i++){
        for(int j = len-1 ; j >i  ; j--){ 
            //注意,这里下标需要从后向前,可以保证每一趟遍历会把奇数移到前面,
            //如果从前向后,则不行,例如 2,4,6,8,1,3,5
            if(arr[j-1]%2 ==0 && arr[j]%2==1){ //前偶后奇
                int temp = arr[j-1];
                arr[j-1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

方法2.2 遇到一个偶数,就向后找到第一个奇数,然后将前面的偶数向后移动一位,将奇数移到前面。

时间复杂度O(n*n) 空间复杂度O(1)

//使用常量的空间
public static void reOrder2(int[] arr) {
    int len = arr.length;
    int i_odd = 1; //指向奇数
    for (int index = 0; index < len; index++) {
        if (arr[index] % 2 == 0) { // 找到一个偶数
            i_odd = Math.max(i_odd, index+1);
            while(i_odd<len){ //注意,i_odd只会向后
                //找到了奇数
                if (arr[i_odd] % 2 == 1) break;        
                i_odd++;
            }
            if(i_odd==len) return; //已经没有未处理的奇数了                    
            
            // 将i到i_odd-1的数字都向后移动一位
            int temp = arr[i_odd];
            for (int cur = i_odd - 1; cur >= index; cur--) {
                arr[cur + 1] = arr[cur];
            }
            arr[index] = temp;    
        }            
    }
} 

 

 

43 maximum subarray iii

问题:
给定一个整数数组和一个整数k,找出k不重叠子数组使得它们的和最大。

每个子数组的数字在数组中的位置应该是连续的。
返回最大的和

样例
给出数组[-1,4,-2,3,-2,3]以及k=2,返回 8

要求:时间复杂度 O(n) 

思路:类似于leetcode中买卖股票的问题,进行K次交易。 

注意:两个问题是有区别的,股票价格总是正的,而且股票求的是收益,而不是股价的和

代码:

public static int maxSubArray(ArrayList<Integer> nums, int k) {
    if (nums == null) return 0;
    int len = nums.size();
    if (len < k) return 0;
    //globalMax[i][j] ,代表从nums[0...j]中找出i个不重叠的子数组的最大和(元素最远到j)
    int[][] globalMax = new int[k + 1][len + 1];
    for (int i = 1; i <= k; i++) {
        int localMax = Integer.MIN_VALUE;
        // 数组长度小于i不能进行划分
        for (int j = i - 1; j < len; j++) {
            localMax = Math.max(localMax, globalMax[i - 1][j])    + nums.get(j);
            if (j == i - 1) //每一行的第一个要单独处理
                globalMax[i][j + 1] = localMax;
            else
                globalMax[i][j + 1] = Math.max(globalMax[i][j], localMax);
        }
    }return globalMax[k][len];
}

 

77 最长公共子序列

给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。

样例
给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1
给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2
注:最长公共子序列不要求一定连续,只要顺序一致即可
方法1:穷举 O(2^m , 2^n)
方法2:递归 O(m*n)+O(m+n) 
public int longestCommonSubsequence(String A, String B) {
    int lenA = A.length();
    int lenB = B.length();    
    //c[i][j]存放的为A[0..i-1] B[0..j-1]的字符串的最大子序列
    /*
     * 若 i==0 || j ==0          则    c[i][j]=0 
     * 若 i,j>0 && A[i]==B[j]    则    c[i][j]=c[i-1][j-1]+1
     * 若 i,j>0 && A[i]!=B[j]    则    c[i][j]=max(c[i-1][j],c[i][j-1]) 
     */
    int[][] c = new int[lenA+1][lenB+1];
    for(int i = 1 ; i <= lenA ; i ++ ){
        for(int j = 1 ; j <= lenB ; j ++ ){
            if(A.charAt(i-1) == B.charAt(j-1)){
                c[i][j] = c[i-1][j-1]+1;
            }else if(c[i-1][j] >= c[i][j-1]){
                c[i][j] = c[i-1][j];
            }else{
                c[i][j] = c[i][j-1];
            }
        }
    }return c[lenA][lenB];    
}

结果:

 
posted @ 2015-10-10 20:04  流了个火  阅读(123)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats