斐波那契数列

题目:输入一个整数n,输出斐波那契数列的第n项(从0开始,第0项为0)。
思路:
  • fabonacci(0) ---> 0
  • fabonacci(2) ---> 1
  • fabonacci(3) ---> 1
  • fabonacci(4) ---> 2
  • fabonacci(5) ---> 3
  • ……
  • fabonacci(n) ---> fabonacci(n-1)+fabonacci(n-2)
public class Fibonacci {
    /**
     * 解法1:递归。
     * 时间复杂度:O(2^n)。
     * 重复计算比较多。
     * @param n
     * @return
     */
    public static int fibonacci1(int n) {
        if (n < 0) {
            throw new RuntimeException("n不能小于0!");
        } else if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else {
            return fibonacci1(n-1) + fibonacci1(n-2);
        }
    }

    /**
     * 解法2:非递归。
     * 时间复杂度:O(n)。
     * @param n
     * @return
     */
    public static int fibonacci2(int n) {
        if (n < 0) {
            throw new RuntimeException("n不能小于0!");
        } else if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else {
            int a = 0;
            int b = 1;
            int res = 0;
            for (int i = 1; i < n; i++) {
                res = a + b;
                a = b;
                b = res;
            }
            return res;
        }
    }
}

跳台阶

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路:
  • 假设青蛙从第n级台阶往下跳,它第一次可以跳到第n-1级台阶或第n-2级台阶。由此递推,即jumpfloor(n)=jumpfloor(n-1)+jumpfloor(n-2)。
  • jumpfloor(1) ---> 1
  • jumpfloor(2) ---> 2
  • jumpfloor(3) ---> 3
  • jumpfloor(4) ---> 5
  • ……
  • jumpfloor(n) ---> jumpfloor(n-1)+jumpfloor(n-2)
public class JumpFloor {
    /**
     * 解法1:递归。
     * @param n
     * @return
     */
    public static int jumpfloor1(int n) {
        if (n < 0) {
            throw new RuntimeException("n不能小于0!");
        } else if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            return jumpfloor1(n - 1) + jumpfloor1(n - 2);
        }
    }

    /**
     * 解法2:非递归。
     * @param n
     * @return
     */
    public static int jumpfloor2(int n) {
        if (n < 0) {
            throw new RuntimeException("n不能小于0!");
        } else if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            int a = 1;
            int b = 2;
            int res = 0;
            for (int i = 2; i < n; i++) {
                res = a + b;
                a = b;
                b = res;
            }
            return res;
        }
    }
}

变态跳台阶

题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路1:
  • jumpFloorII(1) ---> 1
  • jumpFloorII(2) ---> 2
  • jumpFloorII(3) ---> 4
  • jumpFloorII(4) ---> 8
  • ……
  • jumpFloorII(n) ---> 2^(n-1)
思路2:
  • jumpFloorII(n)=jumpFloorII(n-1)+ jumpFloorII(n-2)+……+jumpFloorII(1)
  • jumpFloorII(n-1)=jumpFloorII(n-2)+ jumpFloorII(n-3)+……+jumpFloorII(1)
  • jumpFloorII(n)=2*jumpFloorII(n-1)
public class JumpFloorII {
    public static int jumpFloorII(int n) {
        if (n < 0) {
            throw new RuntimeException("n不能小于0!");
        } else if (n == 0) {
            return 0;
        } else {
            int res = 1;
            for (int i = 1; i < n; i++) {
                res *= 2;
            }
            return res;
        }
    }
}

二维数组中的查找

题目:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:
[
     [1,2,3,4,5],
     [2,3,4,5,6],
     [3,4,5,6,7],
     [4,5,6,7,8]
 ];
从第一行最后一位开始比较,如果target更大,向下移动一位,继续比较;如果target更小,向左移动一位,继续比较;直到找到target返回true,或者遍历完整个数组都没找到,返回false。
public class Solution {
    public boolean Find(int target, int [][] array) {
        int i = 0;
        int j = array[0].length - 1;
        while (i < array.length && j >= 0) {
            if (target == array[i][j]) {
                return true;
            } else if (target > array[i][j]) {
                i++;
            } else {
                j--;
            }
        }
        return false;
    }
}

用两个栈实现队列

题目:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
     
    public void push(int node) {
        stack1.push(node);
    }
     
    public int pop() {
        if(stack1.empty() && stack2.empty()){
            throw new RuntimeException("Queue is empty!");
        }
        if(stack2.empty()){
            while(!stack1.empty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

替换空格

题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
public class Solution {
    public String replaceSpace(StringBuffer str) {
    	StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) == ' ') {
                stringBuffer.append("%20");
            } else {
                stringBuffer.append(str.charAt(i));
            }
        }
        return stringBuffer.toString();
    }
}

旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int length = array.length;
        if(length == 0) {
            return 0;
        }
        int left = 0;
        int right = length-1;
        int mid = 0;
        while(left < right) {
            if(array[left] < array[right]) {
                return array[left];
            }
            mid = (left+right)/2;
            if(array[mid] < array[right]) {
                right = mid;
            } else if(array[mid] > array[right]) {
                left = mid+1;
            } else {
                left++;
            }
        }
        return array[left];
    }
}


调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解法一:使用辅助数组。
public class Solution {
    public void reOrderArray(int [] array) {
        int oddNum = 0;    // array中奇数的个数
        int evenNum = 0;    // array中偶数的个数
        int arrLen = array.length;    // array的长度
        int modVal = 0;    // (arr[i] % 2)
        for(int i = 0; i < arrLen; i++) {
            modVal = array[i] % 2;
            if(modVal != 0) {    // 如果为奇数,oddNum加1
                oddNum++;
            } else {        // 如果为偶数,evenNum加1
                evenNum++;
            }
        }
        int[] oddArr = new int[oddNum];    // 存放奇数的数组
        int[] evenArr = new int[evenNum];    // 存放偶数的数组
        int oddIndex = 0;
        int evenIndex = 0;
        for(int i = 0; i < arrLen; i++) {
            modVal = array[i] % 2;
            if(modVal != 0) {    // 如果为奇数
                oddArr[oddIndex] = array[i];
                oddIndex++;
            } else {        // 如果为偶数
                evenArr[evenIndex] = array[i];
                evenIndex++;
            }
        }
        for(int i = 0; i < arrLen; i++) {
            if(i < oddNum) {
                array[i] = oddArr[i];
            } else {
                array[i] = evenArr[i - oddNum];
            }
        }
    }
}
解法二:冒泡排序。
public class Solution {
    public void reOrderArray(int [] array) {
        int length = array.length;
        int temp;
        for (int i = 1; i < length; i++) {
            for (int j = 0; j < length - i; j++) {
                if (array[j] % 2 == 0 && array[j+1] % 2 == 1) {
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        }
    }
}

包含min函数的栈

题目:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
import java.util.Stack;

public class Solution {
    private Stack<Integer> dataStack = new Stack<>();
    private Stack<Integer> minStack = new Stack<>();
    
    public void push(int node) {
        if (dataStack.isEmpty()) {
            dataStack.push(node);
            minStack.push(node);
        } else {
            dataStack.push(node);
            if(minStack.peek() > node) {
                minStack.push(node);
            } else {
                minStack.push(minStack.peek());
            }
        }
    }
    
    public int pop() {
        if(dataStack.isEmpty()) {
            throw new RuntimeException("栈空!");
        }
        minStack.pop();
        return dataStack.pop();
    }
    
    public int top() {
        return dataStack.peek();
    }
    
    public int min() {
        return minStack.peek();
    }
}

栈的压入、弹出序列

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        int pushLen = pushA.length;
        int popLen = popA.length;
        if(pushLen == 0 || pushLen != popLen) {
            return false;
        }
        Stack<Integer> stack = new Stack<>();
        int index = 0;
        for(int i = 0; i < pushLen; i++) {
            stack.push(pushA[i]);
            while(!stack.isEmpty() && stack.peek() == popA[index]) {
                stack.pop();
                index++;
            }
        }
        return stack.isEmpty();
    }
}

从尾到头打印链表

题目:输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
解法一:借助Stack。
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        Stack<Integer> stack = new Stack<>();
        ListNode cur = listNode;
        while(cur != null) {
            stack.push(cur.val);
            cur = cur.next;
        }
        while(!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;
    }
}
解法二:借助数组。
/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        int length = 0;
        ListNode cur = listNode;
        while(cur != null) {
            length++;
            cur = cur.next;
        }
        int[] vals = new int[length];
        cur = listNode;
        int index = length-1;
        while(cur != null) {
            vals[index--] = cur.val;
            cur = cur.next;
        }
        for(int i = 0; i < length; i++) {
            list.add(vals[i]);
        }
        return list;
    }
}

链表中倒数第k个结点

题目:输入一个链表,输出该链表中倒数第k个结点。
思路:定义两个指针:first、second,让first先走k步,随后first、second一起走,直到first走到终点,此时second指向倒数第k个结点。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode first, second;
        first = second = head;
        int i = 0;
        for (; first != null; i++) {
            if (i >= k)
                second = second.next;
            first = first.next;
        }
        return i < k ? null : second;
    }
}

反转链表

题目:输入一个链表,反转链表后,输出新链表的表头。
解法一:实时调整链表指向。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode newHead = null;
        ListNode temp;
        ListNode cur = head;
        while(cur != null) {
            temp = cur;
            cur = cur.next;
            temp.next = newHead;
            newHead = temp;
        }
        return newHead;
    }
}
解法二:使用Stack。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
import java.util.Stack;
public class Solution {
    public ListNode ReverseList(ListNode head) {
        // 第一种情况:如果head为空,返回null
        if(head == null) {
            return null;
        }
        // 第二种情况:如果head不为空
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while(cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        ListNode newHead = new ListNode(stack.pop().val);
        ListNode node = null;
        cur = newHead;
        while(!stack.isEmpty()) {
            node = new ListNode(stack.pop().val);
            cur.next = node;
            cur = cur.next;
        }
        return newHead;
    }
}

合并两个排序的链表

题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null){
            return list2;
        }else if(list2==null){
            return list1;
        }
        ListNode newHead = null;
        ListNode cur1 = list1;
        ListNode cur2 = list2;
        if(cur1.val < cur2.val) {
            newHead = cur1;
            cur1 = cur1.next;
        } else {
            newHead = cur2;
            cur2 = cur2.next;
        }
        ListNode curHead = newHead;
        while(cur1 != null || cur2 != null) {
            if(cur1 == null) {
                curHead.next = cur2;
                break;
            } else if(cur2 == null) {
                curHead.next = cur1;
                break;
            } else {
                if(cur1.val < cur2.val) {
                    curHead.next = cur1;
                    cur1 = cur1.next;
                    curHead = curHead.next;
                } else {
                    curHead.next = cur2;
                    cur2 = cur2.next;
                    curHead = curHead.next;
                }
            }
        }
        return newHead;
    }
}

复杂链表的复制

题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead) {
        if(pHead == null) {
            return null;
        }
        RandomListNode currentNode = pHead;
        //1、复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
        RandomListNode cloneNode;
        RandomListNode nextNode;
        while(currentNode != null){
            cloneNode = new RandomListNode(currentNode.label);
            nextNode = currentNode.next;
            currentNode.next = cloneNode;
            cloneNode.next = nextNode;
            currentNode = nextNode;
        }
        currentNode = pHead;
        //2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
        while(currentNode != null) {
            currentNode.next.random = currentNode.random == null ? null : currentNode.random.next;
            currentNode = currentNode.next.next;
        }
        //3、拆分链表,将链表拆分为原链表和复制后的链表
        currentNode = pHead;
        RandomListNode pCloneHead = currentNode.next;
        while(currentNode != null) {
            cloneNode = currentNode.next;
            currentNode.next = cloneNode.next;
            cloneNode.next = cloneNode.next == null ? null : cloneNode.next.next;
            currentNode = currentNode.next;
        }
        return pCloneHead;
    }
}

两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null) {
            return null;
        }
        if (pHead1 == pHead2) {
            return pHead1;
        }
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        int k = 0;
        while (p1 != null && p2 != null) {
            p1 = p1.next;
            p2 = p2.next;
        }
        if (p1 != null) {
            while (p1 != null) {
                k++;
                p1 = p1.next;
            }
            p1 = pHead1;
            for (int i = 0; i < k; i++) {
                p1 = p1.next;
            }
            p2 = pHead2;
            while (p1 != p2) {
                p1 = p1.next;
                p2 = p2.next;
            }
            return p1;
        }
        if (p2 != null) {
            while (p2 != null) {
                k++;
                p2 = p2.next;
            }
            p2 = pHead2;
            for (int i = 0; i < k; i++) {
                p2 = p2.next;
            }
            p1 = pHead1;
            while (p1 != p2) {
                p1 = p1.next;
                p2 = p2.next;
            }
            return p1;
        }
        return null;
    }
}
封装后:
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null) {
            return null;
        }
        if (pHead1 == pHead2) {
            return pHead1;
        }
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        int k = 0;
        while (p1 != null && p2 != null) {
            p1 = p1.next;
            p2 = p2.next;
        }
        if (p1 != null) {
            return find(p2, p1, pHead2, pHead1, k);
        }
        if (p2 != null) {
            return find(p1, p2, pHead1, pHead2, k);
        }
        return null;
    }
    
    private ListNode find(ListNode sP, ListNode lP, ListNode sPHead, ListNode lPHead, int k) {
        while (lP != null) {
                k++;
                lP = lP.next;
            }
            lP = lPHead;
            for (int i = 0; i < k; i++) {
                lP = lP.next;
            }
            sP = sPHead;
            while (sP != lP) {
                sP = sP.next;
                lP = lP.next;
            }
            return sP;
    }
}

孩子们的游戏(圆圈中最后剩下的数)

题目:每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1。
解法一:环形链表
class ListNode {
    int val;
    ListNode next = null;
    ListNode(int val) {
        this.val = val;
    }
}
 
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if (n <= 0 || m <= 0) {
            return -1;
        }
        ListNode head = new ListNode(0);
        ListNode node = head;
        for (int i = 1; i < n; i++) {
            node.next = new ListNode(i);
            node = node.next;
        }
        node.next = head;
        int k = 0;
        while (node.next != node) {
            if (++k == m) {
                node.next = node.next.next;
                k = 0;
            } else {
                node = node.next;
            }
        }
        return node.val;
    }
}
解法二:找规律 => f(n, m) = (f(n-1, m) + m) % n
①递归
public class Solution {
    public int fun(int n, int m) {
        if (n <= 0 || m <= 0) return -1;
        return n == 1 ? 0 : (fun(n - 1, m) + m) % n;
    }
}
②循环
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if (n <= 0 || m <= 0) {
            return -1;
        }
        int ans = 0;
        for (int i = 2; i <= n; i++) {
            ans = (ans + m) % n;
        }
        return ans;
    }
}

链表中环的入口结点

题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        if (pHead == null) {
            return null;
        }
        ListNode fastPointer = pHead;
        ListNode slowPointer = pHead;
        while (fastPointer != null && fastPointer.next != null) {
            fastPointer = fastPointer.next.next;
            slowPointer = slowPointer.next;
            if (fastPointer == slowPointer) {
                break;
            }
        }
        if (fastPointer == null || fastPointer.next == null) {
            return null;
        }
        fastPointer = pHead;
        while (fastPointer != slowPointer) {
            fastPointer = fastPointer.next;
            slowPointer = slowPointer.next;
        }
        return fastPointer;
    }
}

二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:
  • 如果一个整数不为0,那么这个整数至少有一位是1。
  • 如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。 其余所有位将不会受到影响。
  • 举个例子:
  • 一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011。
  • 我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。
  • 例如:1100 & 1011 = 1000。
  • 也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        while(n != 0){
            n = n & (n - 1);
            count++;
         }
        return count; 
    }
}

不用加减乘除做加法

题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路:两个二进制的相加结果是用一个异或门实现的;两个二进制的进位结果是用一个与门来实现的。
public class Solution {
    public int Add(int num1,int num2) {
        int result, ans;
        do {
            result = num1 ^ num2;       // 每一位相加
            ans = (num1 & num2) << 1;   // 进位
            num1 = result;
            num2 = ans;
        } while (ans != 0);
        return result;
    }
}

数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路:遍历数组,每两个不同的数相互消除,最后剩下的数就可能是大于一半的数字。
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)return 0;
        int preValue = array[0];//用来记录上一次的记录
        int count = 1;//preValue出现的次数(相减之后)
        for(int i = 1; i < array.length; i++){
            if(array[i] == preValue)
                count++;
            else{
                count--;
                if(count == 0){
                    preValue = array[i];
                    count = 1;
                }
            }
        }
        int num = 0;//需要判断是否真的是大于1半数
        for(int i = 0; i < array.length; i++)
            if(array[i] == preValue)
                num++;
        return (num > array.length/2) ? preValue : 0;
    }
}

整数中1出现的次数(从1到n整数中1出现的次数)

题目:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路一(遍历测试):
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int counts,num;
        counts = 0;
        if(n < 1){
            return 0;
        }
        for(int i = 1;i <= n;i++){
            num = i;
            while(num > 0){
                if(num%10 == 1){
                    counts++;
                }
                num /= 10;
            }
        }
        return counts;
    }
}
思路二:
  • 个位数上的1的个数:(n/10)1 + if(n%10)<1?0:((n%10-1)+1)
  • *十位数上的1的个数:(n/100)10 + if(n%100)<10?0:((n%100-10)+1)
  • *百位数上1的个数:(n/1000)100 + if(n%1000)<100?0:((n%1000-100)+1)
  • *总计i:*(n/(10i))i + if(n%(10i))< i ?0:((n%(10*i)-i)+1),i是小于n的最高位数目:i=pow(10, log10(n))
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        if(n <= 0)return 0;
        int count = 0;
        for(int i=1; i <= n; i*=10){
            //计算在第i位上总共有多少个1
            count = count + (n/(10*i))*i;
            //不足i的部分有可能存在1
            int mod = n%(10*i);
            //如果超出2*i -1,则多出的1的个数是固定的
            if(mod > 2*i -1) {
                count+=i;
            } else{
                //只有大于i的时候才能会存在1
                if(mod >= i) {
                    count += (mod -i)+1;
                }
            }
        }
        return count;
    }
}