總結的筆試/面試算法題

目錄

1. 棧和隊列

1.用兩個隊列實現(xiàn)棧
2.用兩個棧實現(xiàn)隊列
3.實現(xiàn)一個棧桨啃,可以用常數(shù)級時間找出棧中的最小值
4.判斷棧的壓棧、彈棧序列是否合法

2. 鏈表

1.反轉鏈表(使用遞歸和迭代兩種解法檬输,了解頭插法)
2.刪除鏈表的當前節(jié)點
3.刪除倒數(shù)第 k 個節(jié)點
4.兩個有序鏈表合并
5.判斷鏈表是否有環(huán)
6.兩個鏈表的第一個公共節(jié)點(提示:考慮鏈表有環(huán)的情況)
7.刪除鏈表中重復節(jié)點

3. 樹照瘾、二分

1.一個序列,它的形式是12349678丧慈,9是峰值析命,經(jīng)歷了一個上升又下降的過程,找出里面的最大值的位置O(logN)
2.深度優(yōu)先遍歷二叉樹
3.廣度優(yōu)先遍歷二叉樹
4.前序遍歷二叉樹
5.中序遍歷二叉樹
6.輸入一棵二叉樹的根結點,求該樹的深度
7.根據(jù)中序和后序遍歷結果重建二叉樹
8.根據(jù)中序和前序遍歷結果重建二叉樹
9.翻轉二叉樹
10.判斷某個數(shù)組是不是二叉樹的后序遍歷結果
11.二叉樹中和為某個值的路徑
12.二叉樹中某個節(jié)點的下一個節(jié)點

4. 遞歸、動態(tài)規(guī)劃

1.股票買入賣出的最佳時間
2.遞歸方法求數(shù)組的最大值
3.背包問題
4.連續(xù)子數(shù)組的最大和
5.實現(xiàn)簡單的正則表達式匹配

5.字符串

1.給一串字符串比如abbbcccd鹃愤,輸出a1b3c3d1,O(n)
2.例如輸入字符串”I am a student. ”,則輸出”student. a am I”
3.比如輸入字符串”abcefg”和數(shù)字 2,該函數(shù)將返回左旋轉 2 位得到的結”cdefab”
4.判斷是否是回文字符
5.最長回文子串
6.最長無重復子串
7.字符串轉數(shù)字
8.KMP 算法
9.字符串全排列
10.翻轉字符串

6. 排序

1.歸并排序簇搅、拓展:求數(shù)組中的逆序?qū)€數(shù)
2.快速排序 重點:partion 函數(shù)的實現(xiàn)
3.堆排序
4.數(shù)組元素值域已知時,考慮 基數(shù)排序 和 桶排序

7. 大數(shù)據(jù)

1.海量N個數(shù)中求前M大個數(shù)(選擇第M大數(shù))

8. 數(shù)組软吐、矩陣

1.回形馍资,矩陣
2.蛇形矩陣
3.在排序數(shù)組中查找和為給定值的兩個數(shù)字(思路)

9. 位運算

1.給一個十進制數(shù)字,求它的二進制表示中关噪,有多少個 1 (n &= n - 1)
2.給一個數(shù)組鸟蟹,所有數(shù)字都出現(xiàn)了偶數(shù)次,只有一個出現(xiàn)了一次使兔,找出這個數(shù)
3.給一個數(shù)組建钥,所有數(shù)字都出現(xiàn)了三次,只有一個出現(xiàn)了一次虐沥,找出這個數(shù)
4.給一個數(shù)組熊经,所有數(shù)組都出現(xiàn)了偶數(shù)次,只有兩個數(shù)字出現(xiàn)了一次欲险,找出這兩個數(shù)

10. JAVA相關題

1.生產(chǎn)者/消費者(wait() / notify()方法)
2.生產(chǎn)者/消費者(await() / signal()方法)
3.生產(chǎn)者/消費者(BlockingQueue阻塞隊列方法)
4.觀察者設計模式

---持續(xù)跟新镐依,歡迎糾錯---
---【】數(shù)字越大問題越難---
--- 根據(jù)目錄Ctrl C.V快速定位題解答---

棧和隊列

  1. 【2】用兩個隊列實現(xiàn)棧
    public class TwoQueue {
      private LinkedList<String> queue1;
      private LinkedList<String> queue2;
    
    public TwoQueue(){
        queue1 = new LinkedList<String>();
        queue2 = new LinkedList<String>();
    }   
    public String pop(){
        String re =null;
        if(queue1.size() == 0 && queue2.size() == 0){
            return null;
        }
        if(queue2.size() == 0){
            while(queue1.size() >0){
                re = queue1.removeFirst();
                if(queue1.size() != 0){ //最后一個不存進去
                    queue2.addLast(re);
                }
            }
        }else if(queue1.size() == 0){
            while(queue2.size() >0){
                re = queue2.removeFirst();
                if(queue2.size()!=0){
                    queue1.addLast(re);
                }
            }
        }
        return re;
    }
    public String push(String str){
        if(queue1.size() ==0 && queue2.size() == 0){
            queue1.addLast(str);
        }
        if(queue1.size()!=0){
            queue1.addLast(str);
        }else if(queue2.size()!=0){
            queue2.addLast(str);
        }
        return str;
    }
    
  2. 【2】用兩個棧實現(xiàn)隊列
    class MList<T> {
      // 插入棧,只用于插入的數(shù)據(jù)
      private Stack<T> stack1 = new Stack<T>(); // 彈出棧,只用于彈出數(shù)據(jù)
      private Stack<T> stack2 = new Stack<T>();
    
    public MList() {
    }
    
    // 添加操作,入隊
    public void appendTail(T t) {
        stack1.add(t);
    }
    
    // 刪除操作,出隊
    public T deleteHead() {
        // 先判斷彈出棧是否為空,如果為空就將插入棧的所有數(shù)據(jù)彈出棧, // 并且將彈出的數(shù)據(jù)壓入彈出棧中
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.add(stack1.pop());
            }
        }
        // 如果彈出棧中還沒有數(shù)據(jù)就拋出異常
        if (stack2.isEmpty()) {
            throw new RuntimeException("No more element.");
        }
        // 返回彈出棧的棧頂元素,對應的就是隊首元素。
        return stack2.pop();
      }
    }
    
  3. 【2】實現(xiàn)一個棧天试,可以用常數(shù)級時間找出棧中的最小值
  4. 【3】判斷棧的壓棧槐壳、彈棧序列是否合法

鏈表

  1. 【2】反轉鏈表(使用遞歸和迭代兩種解法,了解頭插法)

    public static ListNode reverseList(ListNode head) {
       // 創(chuàng)建一個臨時結點,當作尾插法的邏輯頭結點
       ListNode root = new ListNode();
       // 邏輯頭結點點的下一個結點為空
       root.next = null;
       // 用于記錄要處理的下一個結點
       ListNode next;
       // 當前處理的結點不為空
       while (head != null) {
           // 記錄要處理的下一個結點
           next = head.next;
           // 當前結點的下一個結點指向邏輯頭結點的下一個結點
           head.next = root.next;
           // 邏輯頭結點的下一個結點指向當前處理的結點
           root.next = head;
           // 上面操作完成了一個結點的頭插
           // 當前結點指向下一個要處理的結點
           head = next;
       }
       // 邏輯頭結點的下一個結點就是返回后的頭結點
       return root.next;
    }
    
  2. 【3】刪除鏈表的當前節(jié)點

  3. 【3】刪除倒數(shù)第 k 個節(jié)點

    public static ListNode findKthToTail(ListNode head, int k) 
    { 
      // 輸入的鏈表不能為空,并且k大于0
      if (k < 1 || head == null) {
        return null; 
    }
      // 指向頭結點
      ListNode pointer = head;
      // 倒數(shù)第k個結點與倒數(shù)第一個結點相隔k-1個位置 // pointer先走k-1個位置
      for (int i = 1; i < k; i++) {
        // 說明還有結點
          if (pointer.next != null) {
            pointer = pointer.next; 
          }
        // 已經(jīng)沒有節(jié)點了,但是i還沒有到達k-1說明k太大,鏈表中沒有那么多的元素 
        else {
        // 返回結果
            return null; }
        }
        // pointer還沒有走到鏈表的末尾,那么pointer和head一起走,
        // 當pointer走到最后一個結點即,pointer.next=null時,head就是倒數(shù)第k個結點 
      while (pointer.next != null) {
          head = head.next;
          pointer = pointer.next; 
      }
        // 返回結果
      return head; 
    }
    
  4. 【1】兩個有序鏈表合并

  5. 【2*】判斷鏈表是否有環(huán)

  6. 【3*】兩個鏈表的第一個公共節(jié)點(提示:考慮鏈表有環(huán)的情況)

    public static ListNode findFirstCommonNode(ListNode head1, ListNode head2) {
        int length1 = getListLength(head1); 
        int length2 = getListLength(head2);
        int diff = length1 - length2;
        ListNode longListHead = head1;
        ListNode shortListHead = head2;
        if (diff < 0) {
            longListHead = head2;
            shortListHead = head1;
            diff = length2 - length1;
        }
        for (int i = 0; i < diff; i++) {
            longListHead = longListHead.next;
        }
        while (longListHead != null && shortListHead != null
                && longListHead != shortListHead) {
            longListHead = longListHead.next;
            shortListHead = shortListHead.next;
        }
        // 返回第一個相同的公共結點,如果沒有返回null
        return longListHead;
    }
    
    private static int getListLength(ListNode head) {
        int result = 0;
        while (head != null) {
            result++;
            head = head.next;
        }
        return result;
    }
    
  7. 【3】刪除鏈表中重復節(jié)點


樹喜每、二分

  1. 【2】一個序列务唐,它的形式是12349678,9是峰值带兜,經(jīng)歷了一個上升又下降的過程枫笛,找出里面的最大值的位置O(logN)

    public static int findPeakElement(int [] nums){
      if (nums.length ==1) 
          return 0;
      int low = 0, high = nums.length - 1, mid;
      while (low+1 < high) {
          mid = low + ((high - low) >> 1);
          if (nums[mid] < nums[mid - 1]) 
              high = mid;  //上坡
          else if (nums[mid] < nums[mid+1]) 
              low = mid;   //下坡
          else return mid;
      }
      return nums[low ] >nums[high] ?low:high;
    }
    
  2. 【2】深度優(yōu)先遍歷二叉樹,其實就是前序遍歷

      public void depthOrderTraversal(){
        if(root==null){
            System.out.println("empty tree");
            return;
        }       
        ArrayDeque<TreeNode> stack=new ArrayDeque<TreeNode>();
        stack.push(root);       
        while(stack.isEmpty()==false){
            TreeNode node=stack.pop();
            System.out.print(node.value+"    ");
            if(node.right!=null){
                stack.push(node.right);
            }
            if(node.left!=null){
                stack.push(node.left);
            }           
        }
        System.out.print("\n");
    }
    
  3. 【2】二叉樹廣度優(yōu)先遍歷

    public void levelOrderTraversal(){
    if(root==null){
        System.out.println("empty tree");
        return;
    }
    ArrayDeque<TreeNode> queue=new ArrayDeque<TreeNode>();
    queue.add(root);
    while(queue.isEmpty()==false){
        TreeNode node=queue.remove();  //從隊頭移除
        System.out.print(node.value+"    ");
        if(node.left!=null){
            queue.add(node.left);
        }
        if(node.right!=null){
            queue.add(node.right);
        }
    }
      System.out.print("\n");
    }
    
  4. 前序遍歷二叉樹

      public void preOrderTraverse1(TreeNoderoot){
      if(root!=null){
          System.out.print(root.val+"");
          preOrderTraverse1(root.left);
          preOrderTraverse1(root.right);
      }
    }
    //非遞歸
    public void preOrderTraverse2(TreeNoderoot){
      LinkedList<TreeNode>stack=newLinkedList<>();
      TreeNodepNode=root;
    while(pNode!=null||!stack.isEmpty()){
        if(pNode!=null){
           System.out.print(pNode.val+"");
          stack.push(pNode);
          pNode=pNode.left;
      }else{//pNode==null&&!stack.isEmpty()
          TreeNodenode=stack.pop();
          pNode=node.right;
        }
      }
    }
    
  5. 中序遍歷二叉樹

    public void inOrderTraverse1(TreeNoderoot){
    if(root!=null){
        inOrderTraverse1(root.left);
        System.out.print(root.val+"");
        inOrderTraverse1(root.right);
      }
    }
    //非遞歸
    public void inOrderTraverse2(TreeNoderoot){
    LinkedList<TreeNode>stack=newLinkedList<>();
    TreeNodepNode=root;
    while(pNode!=null||!stack.isEmpty()){
        if(pNode!=null){
            stack.push(pNode);
            pNode=pNode.left;
        }else{//pNode==null&&!stack.isEmpty()
            TreeNodenode=stack.pop();
            System.out.print(node.val+"");
            pNode=node.right;
        }
      }
    }
    
  6. 【2】輸入一棵二叉樹的根結點,求該樹的深度

    public static int treeDepth(BinaryTreeNode root) {
      if (root == null) {
        return 0;
      }
      int left = treeDepth(root.left);
      int right = treeDepth(root.right);
      return left > right ? (left + 1) : (right + 1);
     }
    
  7. 【3】根據(jù)中序和后序遍歷結果重建二叉樹

  8. 【3】根據(jù)中序和前序遍歷結果重建二叉樹

    public static BinaryTreeNode construct(int[] preorder, int ps, int pe,
            int[] inorder, int is, int ie) {
        // 開始位置大于結束位置說明已經(jīng)沒有需要處理的元素了
        if (ps > pe) {
            return null;
        }
        // 取前序遍歷的第一個數(shù)字,就是當前的根結點
        int value = preorder[ps];
        int index = is;
        // 在中序遍歷的數(shù)組中找根結點的位置
        while (index <= ie && inorder[index] != value) {
            index++;
        }
        // 如果在整個中序遍歷的數(shù)組中沒有找到,說明輸入的參數(shù)是不合法的,拋出異常
        if (index > ie) {
            throw new RuntimeException("Invalid input");
        }
        // 創(chuàng)建當前的根結點,并且為結點賦值
        BinaryTreeNode node = new BinaryTreeNode();
        node.value = value;
        // 遞歸構建當前根結點的左子樹,左子樹的元素個數(shù):index-is+1個
        // 左子樹對應的前序遍歷的位置在[ps+1, ps+index-is]
        // 左子樹對應的中序遍歷的位置在[is, index-1]
        node.left = construct(preorder, ps + 1, ps + index - is, inorder, is,
                index - 1); // 遞歸構建當前根結點的右子樹,右子樹的元素個數(shù):ie-index個
        // 右子樹對應的前序遍歷的位置在[ps+index-is+1, pe]
        // 右子樹對應的中序遍歷的位置在[index+1, ie]
        node.right = construct(preorder, ps + index - is + 1, pe, inorder,
                index + 1, ie); // 返回創(chuàng)建的根結點
        return node;
    }
    
  9. 【2】翻轉二叉樹

    public static void mirror(BinaryTreeNode node) { // 如果當前結點不為空則進行操作
      if (node != null) {
      // 下面是交換結點左右兩個子樹
      BinaryTreeNode tmp = node.left;
      node.left = node.right;
      node.right = tmp;
      // 對結點的左右兩個子樹進行處理
      mirror(node.left);
      mirror(node.right);
      }
    }
    
  10. 【3】判斷某個數(shù)組是不是二叉樹的后序遍歷結果 (劍指 offer 第 24 題)

    public static boolean verifySequenceOfBST(int[] sequence, int start, int end) {
        // 如果對應要處理的數(shù)據(jù)只有一個或者已經(jīng)沒有數(shù)據(jù)要處理(start>end)就返回true
        if (start >= end) {
            return true;
        }
        // 從左向右找第一個不大于根結點(sequence[end])的元素的位置
        int index = start;
        while (index < end - 1 && sequence[index] < sequence[end]) {
            index++;
        }
        // 執(zhí)行到此處[end, index-1]的元素都是小于根結點的(sequence[end]) // [end,
        // index-1]可以看作是根結點的左子樹
        // right用于記錄第一個不小于根結點的元素的位置
        int right = index;
        // 接下來要保證[index, end-1]的所有元素都是大于根根點的【A】
        // 因為[index, end-1]只有成為根結點的右子樹
        // 從第一個不小于根結點的元素開始,找第一個不大于根結點的元素
        while (index < end - 1 && sequence[index] > sequence[end]) {
            index++;
        }
        // 如果【A】條件滿足,那么一定有index=end-1,
        // 如果不滿足那說明根結點的右子樹[index, end-1]中有小于等于根結點的元素, // 不符合二叉搜索樹的定義,返回false
        if (index != end - 1) {
            return false;
        }
        // 執(zhí)行到此處說明直到目前為止,還是合法的 // [start, index-1]為根結點左子樹的位置
        // [index, end-1]為根結點右子樹的位置
        index = right;
        return verifySequenceOfBST(sequence, start, index - 1)
                    && verifySequenceOfBST(sequence, index, end - 1);
    }
    
  11. 【3】二叉樹中和為某個值的路徑

        public static void findPath(BinaryTreeNode root, int curSum,
        int expectedSum, List<Integer> result) {
        // 如果結點不為空就進行處理
        if (root != null) {
            // 加上當前結點的值
            curSum += root.value;
            // 將當前結點入隊
            result.add(root.value);
            // 如果當前結點的值小于期望的和
            if (curSum < expectedSum) {
                // 遞歸處理左子樹
                findPath(root.left, curSum, expectedSum, result);
                // 遞歸處理右子樹
                findPath(root.right, curSum, expectedSum, result);
            }
            // 如果當前和與期望的和相等
            else if (curSum == expectedSum) {
                // 當前結點是葉結點,則輸出結果
                if (root.left == null && root.right == null) {
                    System.out.println(result);
                }
            }
            // 移除當前結點刚照,回溯吧
            result.remove(result.size() - 1);
        }
    }
    
  12. 【3*】二叉樹中某個節(jié)點的下一個節(jié)點 (強烈推薦準備一下刑巧,劍指 offer 第 58 題)


遞歸、動態(tài)規(guī)劃

  1. 股票買入賣出的最佳時間
     public int maxProfit(int num[]){
       int max=-1;
       int ans=-1;
       for(inti=len-1;i>=0;i--)
         if(num[i]>max)
           max=num[i];
         if(max-num[i]>ans)
           ans=max-num[i];
     return ans;
    }
    
  2. 【2】遞歸方法求數(shù)組的最大值
    int max(int arr[], int len) {
    if (1 == len){ // 只有一個元素
            return arr[0];
    }
    int a = arr[0]; // 第一個元素
    int b = max(arr + 1, len - 1); // 第二個元素起的最大值
    return a > b ? a : b;
    }
    
  3. 【2】背包問題
  4. 【3】連續(xù)子數(shù)組的最大和
  5. 【4】實現(xiàn)簡單的正則表達式匹配

字符串

  1. 【2】給一串字符串比如abbbcccd无畔,輸出a1b3c3d1,O(n)

    public static void main(String[] args) {
        String str= "abbbcccd";
        int[] count= new int[256];
        for (int i = 0 ;i<str.length();i++) {
            count[str.charAt(i)]++;
        }
        for (int i = 0;i<256;i++) {
            if(count[i]>0){
                System.out.printf("%c%d",i,count[i]);
            }
        }
    }
    
  2. 【2】例如輸入字符串”I am a student. ”,則輸出”student. a am I”

    public static void reverse(char[] data, int start, int end) {
       if (data == null || data.length < 1 || start < 0 || end > data.length
               || start > end) {
           return;
       }
       while (start < end) {
           char tmp = data[start];
           data[start] = data[end];
           data[end] = tmp;
           start++;
           end--;
       }
    }
    
    public static char[] reverseSentence(char[] data) {
       if (data == null || data.length < 1) {
           return data;
       }
       reverse(data, 0, data.length - 1);// 首先全局逆轉
       int start = 0;
       int end = 0;
       while (start < data.length) {
           if (data[start] == ' ') { // 排除開頭空格
               start++;
               end++;
           } else if (end == data.length || data[end] == ' ') {// 單詞結束邊界
               reverse(data, start, end - 1);
               end++;
               start = end;
           } else {
               end++;
           }
       }
       return data;
    }
    
  3. 【2】比如輸入字符串”abcefg”和數(shù)字 2,該函數(shù)將返回左旋轉 2 位得到的結”cdefab”

    public static void reverse(char[] data, int start, int end) {
         if (data == null || data.length < 1 || start < 0 || end > data.length
                 || start > end) {
             return;
         }
         while (start < end) {
             char tmp = data[start];
             data[start] = data[end];
             data[end] = tmp;
             start++;
             end--;
         }
     }
         public static char[] leftRotateString(char[] data, int n) {
         if (data == null || n < 0 || n > data.length) {
             return data;
         }
         reverse(data, 0, data.length - 1);
         reverse(data, 0, data.length - n - 1);
         reverse(data, data.length - n, data.length - 1);
         return data;
     }
    
  4. 【2】java判斷是否是回文字符

    public static boolean isPalidrome(Stringstr){
      char[] ch=str.toCharArray();
      int len=ch.length;
      for(inti=0,intj=len-1;i<=j;){
      if(ch[i++]==ch[j--]){
        }else{
          return false;
        }
      }
      return ture;
    }
    
  5. 【3】最長回文子串

  6. 【3】最長無重復子串

  7. 【1*】字符串轉數(shù)字

  8. 【4】KMP 算法

  9. 【2】字符串全排列

    public static void permutation(char[] chars, int begin) { // 如果是最后一個元素了,就輸出排列結果
        if (chars.length - 1 == begin) {
            System.out.print(new String(chars) + " ");
        } else {
            char tmp;
            // 對當前還未處理的字符串進行處理,每個字符都可以作為當前處理位置的元素
            for (int i = begin; i < chars.length; i++) {
                // 下面是交換元素的位置
                tmp = chars[begin];
                chars[begin] = chars[i];
                chars[i] = tmp;
                // 處理下一個位置
                permutation(chars, begin + 1);
                // 恢復
                tmp = chars[begin];
                chars[begin] = chars[i];
                chars[i] = tmp;
            }
        }
    }```
    
  10. 【2*】翻轉字符串


排序

  1. 歸并排序啊楚、拓展:求數(shù)組中的逆序?qū)€數(shù)
  2. 快速排序 重點:partion 函數(shù)的實現(xiàn)
  3. 堆排序
  4. 數(shù)組元素值域已知時,考慮 基數(shù)排序 和 桶排序

大數(shù)據(jù)

1.【3】海量N個數(shù)中求前M大個數(shù)(選擇第M大數(shù))


數(shù)組檩互、矩陣

  1. 回形矩陣
    public static void spiralOrderPrint(int[][] matrix) {
        int tR = 0;
        int tC = 0;
        int dR = matrix.length - 1;
        int dC = matrix[0].length - 1;
        while (tR <= dR && tC <= dC) {
            printEdge(matrix, tR++, tC++, dR--, dC--);
        }
    }
    
    public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
        if (tR == dR) { // 子矩陣只有一行時
            for (int i = tC; i <= dC; i++) {
                System.out.print(m[tR][i] + " ");
            }
        } else if (tC == dC) { // 子矩陣只有一列時
            for (int i = tR; i <= dR; i++) {
                System.out.print(m[i][tC] + " ");
            }
        } else { // 一般情況
            int curC = tC;
            int curR = tR;
            while (curC != dC) {
                System.out.print(m[tR][curC] + " ");
                curC++;
            }
            while (curR != dR) {
                System.out.print(m[curR][dC] + " ");
                curR++;
            }
            while (curC != tC) {
                System.out.print(m[dR][curC] + " ");
                curC--;
            }
            while (curR != tR) {
                System.out.print(m[curR][tC] + " ");
                curR--;
            }
        }
    }```
    
  2. 蛇形矩陣
  3. 【2】在排序數(shù)組中查找和為給定值的兩個數(shù)字(思路)
    1. 找到數(shù)組的第一個數(shù)字和最后一個數(shù)字特幔。
    2. 當兩個數(shù)字的和大于輸入的數(shù)字時,把較大的數(shù)字往前移動闸昨;
    3. 當兩個數(shù)字的和小于數(shù)字時蚯斯,把較小的數(shù)字往后移動薄风;
    4. 當相等時,輸出等式拍嵌。這樣掃描的順序是從數(shù)組的兩端向數(shù)組的中間掃描遭赂。

位運算

  1. 【2】給一個十進制數(shù)字,求它的二進制表示中横辆,有多少個 1 (n &= n - 1)
  2. 【3】給一個數(shù)組撇他,所有數(shù)字都出現(xiàn)了偶數(shù)次,只有一個出現(xiàn)了一次狈蚤,找出這個數(shù)
  3. 【4】給一個數(shù)組困肩,所有數(shù)字都出現(xiàn)了三次,只有一個出現(xiàn)了一次脆侮,找出這個數(shù)
  4. 【3】給一個數(shù)組锌畸,所有數(shù)組都出現(xiàn)了偶數(shù)次,只有兩個數(shù)字出現(xiàn)了一次靖避,找出這兩個數(shù)

JAVA相關題

  1. 【2】生產(chǎn)者/消費者(wait() / notify()方法)

    public class Storage {
    // 倉庫最大存儲量
    private final int MAX_SIZE = 100;
    // 倉庫存儲的載體
    private LinkedList<Object> list = new LinkedList<Object>();
    
    // 生產(chǎn)num個產(chǎn)品
    public void produce(int num) {
        // 同步代碼段
        synchronized (list) {
            // 如果倉庫剩余容量不足
            while (list.size() + num > MAX_SIZE) {
                try {
                    list.wait();    // 由于條件不滿足潭枣,生產(chǎn)阻塞
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 生產(chǎn)條件滿足情況下,生產(chǎn)num個產(chǎn)品
            for (int i = 1; i <= num; ++i) {
                list.add(new Object());
            }
            list.notifyAll();
        }
    }
    
    // 消費num個產(chǎn)品
    public void consume(int num) {
        // 同步代碼段
        synchronized (list) {
            // 如果倉庫存儲量不足
            while (list.size() < num) {
                try {
                    list.wait();    // 由于條件不滿足幻捏,消費阻塞
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            // 消費條件滿足情況下盆犁,消費num個產(chǎn)品
            for (int i = 1; i <= num; ++i) {
                list.remove();
            }
            list.notifyAll();
        }
    }
    }
    
  2. 【3】生產(chǎn)者/消費者(await() / signal()方法)

    public class Storage  {  
    // 倉庫最大存儲量  
    private final int MAX_SIZE = 100;  
    // 倉庫存儲的載體  
    private LinkedList<Object> list = new LinkedList<Object>();  
    // 鎖  
    private final Lock lock = new ReentrantLock();  
    // 倉庫滿的條件變量  
    private final Condition full = lock.newCondition();  
    // 倉庫空的條件變量  
    private final Condition empty = lock.newCondition();  
    
    // 生產(chǎn)num個產(chǎn)品  
    public void produce(int num)      {  
      // 獲得鎖  
      lock.lock();  
      // 如果倉庫剩余容量不足  
      while (list.size() + num > MAX_SIZE)   {  
          try  {  
              full.await();   // 由于條件不滿足,生產(chǎn)阻塞  
          }  
          catch (InterruptedException e)  {  
              e.printStackTrace();  
          }  
      }  
    
      // 生產(chǎn)條件滿足情況下篡九,生產(chǎn)num個產(chǎn)品  
      for (int i = 1; i <= num; ++i)    {  
          list.add(new Object());  
      }  
    
      // 喚醒其他所有線程  
      full.signalAll();  
      empty.signalAll();  
    
      // 釋放鎖  
      lock.unlock();  
    }  
    
    // 消費num個產(chǎn)品  
    public void consume(int num)  {  
      // 獲得鎖  
      lock.lock();  
    
      // 如果倉庫存儲量不足  
      while (list.size() < num)   {  
          try  {  
              empty.await();  // 由于條件不滿足谐岁,消費阻塞  
          }  
          catch (InterruptedException e)   {  
              e.printStackTrace();  
          }  
      }  
    
      // 消費條件滿足情況下,消費num個產(chǎn)品  
      for (int i = 1; i <= num; ++i)  {  
          list.remove();  
      }  
    
      // 喚醒其他所有線程  
      full.signalAll();  
      empty.signalAll();  
    
      // 釋放鎖  
      lock.unlock();  
    }  
    }
    
  3. 【2】生產(chǎn)者/消費者(BlockingQueue阻塞隊列方法)

    public class Storage  
    {  
    // 倉庫最大存儲量  
    private final int MAX_SIZE = 100;  
    // 倉庫存儲的載體  
    private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>(100);  
    
    // 生產(chǎn)num個產(chǎn)品  
    public void produce(int num)  {  
        // 如果倉庫剩余容量為0  
        if (list.size() == MAX_SIZE)  {  
            System.out.println("暫時不能執(zhí)行生產(chǎn)任務!");  
        }  
    
        // 生產(chǎn)條件滿足情況下瓮下,生產(chǎn)num個產(chǎn)品  
        for (int i = 1; i <= num; ++i)  {  
            try  {  
                // 放入產(chǎn)品翰铡,自動阻塞  
                list.put(new Object());  
            }  
            catch (InterruptedException e)  {  
                e.printStackTrace();  
            }   
        }  
    }  
    
    // 消費num個產(chǎn)品  
    public void consume(int num)  
    {  
        // 如果倉庫存儲量不足  
        if (list.size() == 0)  {  
            System.out.println("暫時不能執(zhí)行消費任務!");  
        }  
    
        // 消費條件滿足情況下,消費num個產(chǎn)品  
        for (int i = 1; i <= num; ++i)  {  
            try  {  
                // 消費產(chǎn)品讽坏,自動阻塞  
                list.take();  
            }  
            catch (InterruptedException e)  {  
                e.printStackTrace();  
            }  
        }  
     }  
    } 
    
  4. 【3】觀察者設計模式

     public class SimpleObservable extends Observable{    
     private int data = 0;    
     public int getData(){     
       return data;    
    }     
     public void setData(int i){    
       if(this.data != i) {   
          this.data = i;   
          setChanged();    
          //只有在setChange()被調(diào)用后,notifyObservers()才會去調(diào)用update()例证,否則什么都不干路呜。  
          notifyObservers();      
       }    
     }    
    } 
    public class SimpleObserver implements Observer{    
     public SimpleObserver(SimpleObservable simpleObservable){    
      simpleObservable.addObserver(this );    
    }        
     public void update(Observable observable ,Object data){  // data為任意對象,用于傳遞參數(shù)  
      System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());    
     }    
    } 
    public class SimpleTest{    
     public static void main(String[] args){    
      SimpleObservable doc = new SimpleObservable ();    
      SimpleObserver view = new SimpleObserver (doc);    
      doc.setData(1);    
      doc.setData(2);    
      doc.setData(2);    
      doc.setData(3);     
       }    
    }   
    
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末织咧,一起剝皮案震驚了整個濱河市胀葱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笙蒙,老刑警劉巖抵屿,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捅位,居然都是意外死亡轧葛,警方通過查閱死者的電腦和手機搂抒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尿扯,“玉大人求晶,你說我怎么就攤上這事≈运瘢” “怎么了芳杏?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辟宗。 經(jīng)常有香客問我爵赵,道長,這世上最難降的妖魔是什么泊脐? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任空幻,我火速辦了婚禮,結果婚禮上晨抡,老公的妹妹穿的比我還像新娘氛悬。我一直安慰自己,他們只是感情好耘柱,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布如捅。 她就那樣靜靜地躺著,像睡著了一般调煎。 火紅的嫁衣襯著肌膚如雪镜遣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天士袄,我揣著相機與錄音悲关,去河邊找鬼。 笑死娄柳,一個胖子當著我的面吹牛寓辱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赤拒,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼秫筏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挎挖?” 一聲冷哼從身側響起这敬,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕉朵,沒想到半個月后棺弊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體众羡,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡鹏往,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缭保。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡帝雇,死狀恐怖涮俄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尸闸,我是刑警寧澤彻亲,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站吮廉,受9級特大地震影響苞尝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宦芦,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一宙址、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧调卑,春花似錦抡砂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至溯捆,卻和暖如春丑搔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背提揍。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工啤月, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劳跃。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓谎仲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親刨仑。 傳聞我的和親對象是個殘疾皇子强重,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,743評論 0 33
  • 1. Java基礎部分 基礎部分的順序:基本語法贸人,類相關的語法,內(nèi)部類的語法佃声,繼承相關的語法艺智,異常的語法,線程的語...
    子非魚_t_閱讀 31,622評論 18 399
  • Java經(jīng)典問題算法大全 /*【程序1】 題目:古典問題:有一對兔子圾亏,從出生后第3個月起每個月都生一對兔子十拣,小兔子...
    趙宇_阿特奇閱讀 1,860評論 0 2
  • 一封拧、 1、請用Java寫一個冒泡排序方法 【參考答案】 public static void Bubble(int...
    獨云閱讀 1,367評論 0 6
  • 親愛的姑娘夭问,我知道你今天一定很喜歡那種感覺泽西,當你投入到你安身立命的事物中,可以逐漸感受到自己的底氣在一點點增加缰趋,且...
    圖小圖閱讀 522評論 0 0