算法相关问题以及对应解

LintCode上的算法相关的问题,以及相对应的解,所有答案用Java实现

斐波那契数列

查找斐波纳契数列中第 N 个数的和。
所谓的斐波纳契数列是指:

  • 前2个数是 0 和 1 。
  • 第 i 个数是第 i-1 个数和第i-2 个数的和。

斐波纳契数列的前10个数字是:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...

答案解析

public class Solution {
    /**
     * @param n: an integer
     * @return: an ineger f(n)
     */
    public int fibonacci(int n) {
        // write your code here
          int a = 0;
          int b = 1;
          for (int i=0;i<n-1;i++){
              int c = a+b;
              a=b;
              b=c;
          }
          return a;
    }
}

删除链表中的元素

删除链表中等于给定值val的所有节点。

样例
给出链表 1->2->3->3->4->5->3, 和 val = 3, 你需要返回删除3之后的链表:1->2->4->5

答案解析
建立一个新的节点添加到链表的起始位置,例如:new->1->2->3->3->4->5->3,然后从起始位置移动节点,当遇到要删除的节点时,将该节点删除,否则继续移动,直到遍历完所有的节点,最后返回去掉起始节点的链表。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    /*
     * @param head: a ListNode
     * @param val: An integer
     * @return: a ListNode
     */
    public ListNode removeElements(ListNode head, int val) {
        // write your code here
        ListNode node = new ListNode(0);
        node.next = head;
        head=node;
        while (head.next != null){
            if (head.next.val == val){
                head.next = head.next.next;
            }
            else{
                head = head.next;
            }

        }
        return node.next;

        }
}

整数排序

给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法。

样例
对于数组 [3, 2, 1, 4, 5], 排序后为:[1, 2, 3, 4, 5]。

  • 选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

答案

public class Solution {
    /**
     * @param A an integer array
     * @return void
     */
    public void sortIntegers(int[] A) {
        // Write your code here
        int n = A.length;
        for (int i = 0; i < n; ++i)
            for (int j = i+1; j < n; ++j)
                if (A[j] < A[i]) {
                    int t = A[j];
                    A[j] = A[i];
                    A[i] = t;
                }
    }
}for
  • 冒泡排序规则:
    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

答案

public class Solution {
    /**
     * @param A: an integer array
     * @return: nothing
     */
    public void sortIntegers(int[] A) {
        // write your code here
        int len = A.length;
        int temp;
        for (int i = 0;i<len-1;i++){
            for(int j = 0;j<len-i-1;j++){
                if(A[j]>A[j+1]){
                    temp=A[j];
                    A[j]=A[j+1];
                    A[j+1]=temp;
                }
            }
        }
    }
}
  • 插入排序:是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

答案

public class Solution {
    /**
     * @param A: an integer array
     * @return: nothing
     */
    public void sortIntegers(int[] A) {
        // write your code here
        int len = A.length;
        int temp;
        for (int i = 0;i<len-1;i++){
            for(int j = i+1;j>0;j--){
                if(A[j]>A[j-1]){
                    break;
                }
                temp = A[j];
                A[j] = A[j-1];
                A[j-1] = temp;
            }
        }
    }
}

二叉树的最大节点

在二叉树中寻找值最大的节点并返回。

样例

     1  
   /   \    
 -5     2   
 / \   /  \     
0   3 -4  -5    

答案解析

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /*
     * @param root: the root of tree
     * @return: the max node
     */
    public TreeNode maxNode(TreeNode root) {
        // write your code here
        if (root == null)
            return root;
        TreeNode right = maxNode(root.right);
        TreeNode left = maxNode(root.left);

        return max(root,max(right,left));

    }
    private TreeNode max(TreeNode a,TreeNode b){
        if (a == null)
            return b;
        if (b == null)
            return a;
        if (a.val > b.val) {
            return a;
        }
        return b;
    }

}

A + B 问题

给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。

答案解析

主要利用异或运算来完成,异或运算有一个别名叫做:不进位加法,那么a ^ b就是a和b相加之后,该进位的地方不进位的结果,然后下面考虑哪些地方要进位,自然是a和b里都是1的地方,a & b就是a和b里都是1的那些位置,a & b << 1 就是进位之后的结果。所以:a + b = (a ^ b) + (a & b << 1)令a’ = a ^ b, b’ = (a & b) << 1 可以知道,这个过程是在模拟加法的运算过程,进位不可能一直持续,所以b最终会变为0。因此重复做上述操作就可以求得a + b的值。

public class Solution {
    /**
     * @param a: An integer
     * @param b: An integer
     * @return: The sum of a and b
     */
    public int aplusb(int a, int b) {
        while(b!=0){
            int _a = a^b;
            int _b = (a&b)<<1;
            a = _a;
            b= _b;
        }
        return a;
    }
}

尾部的零

设计一个算法,计算出n阶乘中尾部零的个数

样例
11! = 39916800,因此应该返回 2

答案解析
要求n的阶乘,就是求1到n这n个数相乘。在这1到n个数当中,只有2和5相乘的结果才会出现0,其中10的倍数也可以看做是2和5相乘的结果,所以,可以在1到n之间看看有多少个数是2的倍数以及多少个数是5的倍数就行了。容易发现2的倍数的数一定多于5的倍数的数,因此可以只看n前面有多少个5就行了,于是n/5可以得到1到n内有多少个数是5的倍数。此外,还有一些特殊情况,比如25这种,其是5和5相乘的结果,这种数和4相乘会出现2个0,同理125和8相乘会出现3个0,……,所以,还要看n/5里面有多少个5,比如n=125,125个数里有25个数是5的倍数,125里又有125/25=5个数是25的倍数。每个25的倍数又会多一个0。因此125! 的末尾0的个数就是125/5 + 125/5/5 + 125/5/5/5。其中最后一项表示125的个数,因为125和8相乘会出现3个0。如果下面还有,比如625,即需要再循环一次,就是625的个数,625乘以16会出现4个0,需要再加1,依次类推……

public class Solution {
    /*
     * @param n: An integer
     * @return: An integer, denote the number of trailing zeros in n!
     */
    public long trailingZeros(long n) {
        // write your code here, try to do it without arithmetic operators.
        long sum = 0;
        while(n!=0)
        {
            n /= 5;
            sum += n;
        }
        return sum;
    }
}

合并排序数组

合并两个排序的整数数组A和B变成一个新的数组。

样例

给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6]

答案解析

public class Solution {
    /**
     * @param A: sorted integer array A
     * @param B: sorted integer array B
     * @return: A new sorted integer array
     */
    public int[] mergeSortedArray(int[] A, int[] B) {
       int[] ans = new int[A.length + B.length];
        int a = 0, b = 0, temp = 0;
        while(a != A.length && b != B.length) {
            if(A[a] > B[b]){
                ans[temp] = B[b++];
            }
            else {
                ans[temp] = A[a++];
            }
            temp ++;
        }
        if(a != A.length){
            while(a != A.length){
                ans[temp++] = A[a++];
            }
        }
        else {
            while(b != B.length){
                ans[temp++] = B[b++];
            }
        }
        return ans;
    }
}

旋转字符串

给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转)
样例
对于字符串 “abcdefg”.

offset=0 => "abcdefg"
offset=1 => "gabcdef"
offset=2 => "fgabcde"
offset=3 => "efgabcd"

答案解析

public class Solution {
    /**
     * @param str: an array of char
     * @param offset: an integer
     * @return: nothing
     */
    public void rotateString(char[] str, int offset) {
        // write your code here
        if (str == null || str.length == 0)
            return;

        offset = offset % str.length;
        reverse(str, 0, str.length - offset - 1);
        reverse(str, str.length - offset, str.length - 1);
        reverse(str, 0, str.length - 1);
    }

    private void reverse(char[] str, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            char temp = str[i];
            str[i] = str[j];
            str[j] = temp;
        }
    }
}

字符串查找

对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1。

样例
如果 source = “source” 和 target = “target”,返回 -1。
如果 source = “abcdabcdefg” 和 target = “bcd”,返回 1。

答案解析

class Solution {
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    public int strStr(String source, String target) {
        if (source == null || target == null) {
            return -1;
        }

        for (int i = 0; i < source.length() - target.length() + 1; i++) {
            int j = 0;
            for (j = 0; j < target.length(); j++) {
                if (source.charAt(i + j) != target.charAt(j)) {
                    break;
                }
            }
            // finished loop, target found
            if (j == target.length()) {
                return i;
            }
        }
        return -1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值