1. 程式人生 > 實用技巧 >LZW演算法壓縮字串資料

LZW演算法壓縮字串資料

連結串列

  1. resursion 遞迴的原理;細節
/*Calculating Fibonacci value
int fibo(int n){  //檢查check是否要停下,   
if(n == 0)retutn 0;                           //base case o(1)
else  if{n ==1}
else{
return fibo(n-1)+fibo(n-2); }
}
Call stack; //全域性的變數,Usage; store the local information for each recursion function  
                   F(4)
                //      \\
          F(3)            F(2 )
        /       \              \
    F(2)        F(1)
question 1: interview  question on linkedlist:how to reserver a linked list
            node1  -> node2 ->node3 ->node4 ->null
             head
 pre       cur           next
              pre (a)          cur(temp)            next(b)
public    linkNode     reverseLinkdelist(linkedNode  head){                                
         if(head == null||head.next) return head;
          linkedNode   pre = null;
          linkedNode   cur = head;
          while(cur!=null){
               LinkedNode  next = cur.next;//記錄next的值。
               cur.next  = pre;
               pre = cur;
                cur  = next;
          }   
}
method:遞迴
before    node1 ->node2 ->node3 ->null
after       null <- node1  < - node2  <- node3
 next.next  = head;
 next. = null;
public static  LinkedNode  reserverLinked(LinkedNode  head){
  if(head==null||head.next==null)return head;
    LinkedNode new_head = resercerLinked(head.next); 
    head.next.next = head;
    head.next = null;
   return new_head;
}
question 2How to create a linked list node
class  Node{
     int  no ;
     String name;
      Node  next;
     public Node(int no,String name){
        this.no = no;
        this.name = name;
   }
    public String toString() {
            return "HeroNode [no= " + no + "name =" + name + "]";
      }
}
question 3How to add  data
public static  void  add(LinkedNode  value){
    LinkedNode temp = value;
    while(temp.next!=null){
        temp = temp.next;
     }
    temp.next = head;
}
question How to find the middle node of a linked list?
  N1 ->N2 ->N3   ->N4 ->N5 ->null
   fast     
   slow
   N1 ->N2 ->N3   ->N4 ->N5 ->null
             sl
public static Node middle(Node head){
if (head==null)return null;
   Node fast = head;
     Node slow = head;
while (fast.next!=null && fast.next.next!=null){
       fast = fast.next.next;
        slow = slow.next;
        }
      return slow;
}
question:判斷是否有環
public static boolean midde (Node head){
     if(head==null)return false;
else if(head!=null && head.next==null)
    return true;
   Node fast = head , slow = head;
while(fast.next.next != null){
   fast = head.next;
     slow = head.next;
   }
if(fast.next==slow)return true;
     else return false;
}
question :insert a node in a sort linked;
public static Node insert(Node head ,Node a){
if (head == null || a == null)return null;
boolean flag = false;
Node temp = head;
while (true){
if (temp.next==null)break;
if (a.no>temp.no&&a.no<=temp.next.no)break;
if (a.no > temp.no &&a.no<=temp.next.no){
flag=true;
break;
}
temp = temp.next;
}
if (flag){
return null;
}
else {
a.next = temp.next;
temp.next = a;
return head;
}
}
question  How  to list data
public static void list(){
     if(head==null){
      System.out.println("空");
       return;
}
    Node temp = head;
     while(true){
         if (temp!=null) {
          System.out.println(temp);
          temp = temp.next;
       }
     }
}
question ;How to merger tow lists?
public static Node newLinked(Node head,Node head1) {
Node ss = new Node(-1, "aa");
Node s = ss;
while (head!=null&&head1!=null){
if (head.no>=head1.no){
s.next = head1;
head1 = head1.next;
s=s.next;
}else {
s.next = head;
head = head.next;
s=s.next;
}
}
s.next = (head!=null)?head:head1;
return ss.next;
}
public static Node newLinked(Node head, Node head1) {

if (head == null) return head1;
if (head1 == null) return head;
if (head.no < head1.no) {
head.next = newLinked(head.next, head1);
return head;
} else {
head1.next = newLinked(head, head1.next);
return head1;
}

}

判斷字串String是否為空問題

判斷字串String是否為空問題
一、判斷一個字串str不為空的方法有:
1、str == null;
2、"".equals(str);
3、str.length <= 0;
4、str.isEmpty();
注意:length是屬性,一般集合類物件擁有的屬性,取得集合的大小。
例如:陣列。length就是取得陣列的長度。
length()是方法,一般字串類物件有該方法,也是取得字串長度。
例如:字串。length();
說明:
1、null表示這個字串不指向任何的東西,如果這時候你呼叫它的方法,那麼就會出現空指標異常。
2、""表示它指向一個長度為0的字串,這時候呼叫它的方法是安全的。
3.、null不是物件,"“是物件,所以null沒有分配空間,”"分配了空間,例如:
String str1 = null; str引用為空
String str2 = ""; str引用一個空串
str1還不是一個例項化的物件,而str2已經例項化。
物件用equals比較,null用等號比較。
如果str1=null;下面的寫法錯誤:
if(str1.equals("")||str1null){ }
正確的寫法是 if(str1
null||str1.equals("")){ //所以在判斷字串是否為空時,先判斷是不是物件,如果是,再判斷是不是空字串 }
4.所以,判斷一個字串是否為空,首先就要確保他不是null,然後再判斷他的長度。
String str = xxx;
if(str != null && str.length() != 0) { }

排序

快排

連線:https://www.bilibili.com/video/BV1at411T75o? from=search&seid=3067293629631568894

private static int Partition(int[] arr, int start, int end) {
//arr[start]為挖的第一個坑
int temp = arr[start];
   while (end > start){
   while(end > start&&arr[end]>=temp)
    end--;
    arr[start] = arr[end];
 while (end>start&&arr[start]<=temp)
    start++;
    arr[end] = arr[start];
  }
   arr[start] = temp;
   return start;
}
public static void quickSort(int[] arr, int start ,int end){
  if (start < end){
  int index = Partition(arr,start,end);
  Partition(arr,start,index-1);
  Partition(arr,index+1,end);
  }
}

選擇排序

public static void main(String[] args) {
  int[] arr = {2, 5, 3, 5, 1, 5, 6};
  for (int i = 0; i < arr.length; i++) {
  //先設定最小值,和索引
  int min = arr[i];
  int index = i;
  for (int j = i + 1; j < arr.length; j++) {
  //將最小值交換下
  if (min > arr[j]) {
  min = arr[j];
  index = j;
   }
}
//判斷是否交換沒,交換了再進行交換
if (index != i) {
   arr[index] = arr[i];
  arr[i] = min;
  }
}
   System.out.println(Arrays.toString(arr));
}
public static void sortMrger(int[] arr, int left, int right, int[] temp) {

if (left <right) {
int mid = left +(right - left) /2;
sortMrger(arr, left, mid, temp);
sortMrger(arr, mid + 1, right, temp);
merge(arr, left, mid, right, temp);
}
}

public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
//建立左半部分的最高索引
int i = mid + 1;//初始化右邊的,因為在左邊的第一個
int j = left;
//設定索引
int t = 0;
while (i <=right && j <= mid) {
if (arr[i] <= arr[j]) {
    temp[t] = arr[i];
    i++;
    t++;
  }
if (i<=right&&arr[i] >= arr[j]) {
   temp[t] = arr[j];
   j++;
   t++;
   }
 }
while (j <= mid) {
temp[t] = arr[j];
   j++;
  t++;
}
while (i <= right) {
temp[t] = arr[i];
     i++;
     t++;
    }
    int r = left;
    t = 0;
while (r <= right) {
   arr[r] = temp[t];
    r++;
   t++;
  }
}

氣泡排序

public class 氣泡排序 {
public static void main(String[] args)  {
int[] arr = {2, 5, 3, 5, 7, 8, 6};
int temp = 0;
boolean flag = false;//如果只有一個數交換,不需要一直遍歷,來減輕方便的
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1; j++) {
if (arr[j] > arr[j + 1]) {
  flag = true;
  temp = arr[j + 1];
  arr[j + 1] = arr[j];
  arr[j] = temp;
  }
}
if (!flag) {
break;
} else {
flag = false;
}
}
System.out.println(Arrays.toString(arr));
}

堆排序

public static void main(String[] args) {
int[] arr= {2,5,3,6,4,1,2,8};
new HeapSort().heap(arr);
System.out.println(Arrays.toString(arr));
}
}
class HeapSort{
public void heap(int[] arr){
int temp = 0;//交換最後一個值後第一個值的臨時變數
for(int i = arr.length/2-1;i>=0;i--){
heapSort(arr,i,arr.length);//先求出第一次的頭
}
for(int j = arr.length - 1; j > 0;j--){
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
heapSort(arr,0,j);//出去最後一個值後縮小索引
}
}
public void heapSort(int[] arr, int i, int leng) {
/*
思路: 先將從最後一個非葉子結點開始,arr.length/2 - 1,從左到右,從下到上
*/
//設定一個臨時變數來放頂頭值
int temp = arr[i];
//將當前的頂結點的值給算出來
for (int k = i * 2 + 1; k < leng; k *= 2 + 1) {
//k+1總是會小於leng。當不是滿二叉樹,不需要判斷了
if (k + 1 < leng && arr[k] < arr[k + 1]) {
k = k + 1;
}
if (arr[k] > temp) {
arr[i] = arr[k];
i = k;//將交換的數值後索引交換
} else {
break;
}
}
arr[i] = temp;
}

插入排序

public static void main(String[] args) {
int[] arr = {2, 5, 3, 6, 4, 2, 5, 1, 2};
charu(arr);
  System.out.println(Arrays.toString(arr));
}
public static void charu(int[] arr){
  for (int i = 1;i<arr.length;i++){
  int temp = arr[i];
  int index = i -1;
  while (index >= 0 && arr[index]>=temp){
   arr[index+1] = arr[index];
  index--;
  }
   arr[index+1] = temp;
  }
}

queue stack deque

linkedlist 可以新增null,arrayQueue不可以
peek 是返回頂點元素 , 不會刪除的,pop 是返回你取得元素,還要刪除呢

queue 和 stack ,deque(deck發音)實現類Linkedlist 和arrayDueue

Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
queue.offer(3);
while (!queue.isEmpty()){
System.out.println(queue.peek());
System.out.println(queue.poll());
}
System.out.println(queue.peek());
System.out.println(queue.poll());
Deque<Integer> deque = new LinkedList<>();
deque.offerFirst(1);
deque.offerFirst(2);
deque.offerFirst(3);
deque.offerLast(4);
deque.offerLast(5);
deque.offerLast(6);
for (int i = 0;i<deque.size();i++){
if (i%2==0){
System.out.println(deque.peekFirst());
System.out.println(deque.pollFirst());
}
}
class ListNode{
int value;
ListNode next;
public ListNode(int value){
   this.value = value;
}

}
class Stack{
ListNode head ;
public Stack(){
head = new ListNode(1);
head.next = null;
}
public void push(int value){
ListNode newNode = new ListNode(value);
newNode.next = head.next;
head.next = newNode;
}
public Integer pop(){
ListNode temp = head.next;
if (head.next == null){
return null;
}
head.next = temp.next;
temp.next = null;
return temp.value;
}
public Integer peek(){
return head.next.value;
}

tree

但是,二叉搜尋樹對雜湊表的效能很好:

  1. 二進位制搜尋樹永遠不會遇到衝突,這意味著二進位制搜尋樹可以保證在O(log(n))中實現插入,檢索和刪除,這比線性時間快得多。此外,樹所需的空間與輸入資料的大小完全相同。
  2. 您無需事先知道輸入大小。
  3. 對樹中的所有元素進行排序,以使有序遍歷花費O(n)時間。
    好,讓我做一個總結。
    如果您知道要維護多少資料,並且有足夠的空間儲存雜湊表並且不需要對資料進行排序,那麼雜湊表始終是不錯的選擇。因為,雜湊表為插入,檢索和刪除提供了恆定時間的操作。另一方面,如果將始終新增項,則與執行時的雜湊處理操作相比,二叉搜尋樹的O(log(n))操作是可以接受的。
    此外,如果您實際上不知道輸入專案的大小,但是在插入後,大多數操作都是在查詢專案,由於檢索時間恆定,因此首選雜湊表。但是,如果連續新增或刪除專案,則樹的O(log(n))插入和刪除時間更適合這種情況。
    一言以蔽之,沒有人會回答雜湊表或樹更好。我們需要知道的是在不同條件下雜湊表和樹的優缺點。可以通過了解這兩種結構的利益和權衡來做出最佳決策。
    一種二叉查詢樹,但在每個節點增加一個儲存位表示節點的顏色,可以是紅或黑(非紅即黑)。通過對任何一條從根到葉子的路徑上各個節點著色的方式的限制,紅黑樹確保沒有一條路徑會比其它路徑長出兩倍,因此,紅黑樹是一種弱平衡二叉樹(由於是弱平衡,可以看到,在相同的節點情況下,AVL樹的高度低於紅黑樹),相對於要求嚴格的AVL樹來說,它的旋轉次數少,所以對於搜尋,插入,刪除操作較多的情況下,我們就用紅黑樹。
    Attention:
  • 平衡樹(AVL)是為了解決 二叉查詢樹(BST)退化為連結串列的情況。
  • 紅黑樹(RBT)是為了解決 平衡樹 在刪除等操作需要頻繁調整的情況

查詢多的話用 AVL ,
新增刪除多的話用 RB。

二叉樹 滿二叉樹 完全二叉樹 堆和堆排序
定義 二叉樹是節點的有限集合,該集合或為空集,或由一個根元素和兩棵不相交的二叉樹組成(遞迴定義)二叉樹的兩棵子樹分別稱為它的左子樹和右子樹 一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹。也就是說,如果一個二叉樹的層數為K,且結點總數是(2^k) -1 ,則它就是滿二叉樹。 一棵二叉樹至多隻有最下面的兩層上的結點的度數可以小於2,並且最下層上的結點都集中在該層最左邊的若干位置上,則此二叉樹成為完全二叉樹,並且最下層上的結點都集中在該層最左邊的若干位置上,而在最後一層上,右邊的若干結點缺失的二叉樹,則此二叉樹成為完全二叉樹。 [1] 堆的結構可以分為大根堆和小根堆,是一個完全二叉樹,而堆排序是根據堆的這種資料結構設計的一種排序,下面先來看看什麼是大根堆和小根堆
性質 性質1. 非空二叉樹第 i 層上至多有 2i 個結點(i ≥ 0)性質2. 高度為 k 的二叉樹至多有 2k-1 個結點(k ≥ 0)性質3. 對任何非空二叉樹 T,若其葉結點個數為 n0,度數為 2 的結點個數為 n2,則n0 = n2 + 1性質4. n 個結點的完全二叉樹的高度 k = ⎡log2(n+1)⎤性質5. 滿二叉樹裡的葉結點比分支結點多一個 如果一棵具有n個結點的深度為k的二叉樹,它的每一個結點都與深度為k的滿二叉樹中編號為1~n的結點一一對應,這棵二叉樹稱為完全二叉樹。可以根據公式進行推導,假設n0是度為0的結點總數(即葉子結點數),n1是度為1的結點總數,n2是度為2的結點總數,則 :①n= n0+n1+n2 (其中n為完全二叉樹的結點總數);又因為一個度為2的結點會有2個子結點,一個度為1的結點會有1個子結點,除根結點外其他結點都有父結點,②n= 1+n1+2n2 ;由①、②兩式把n2消去得:n= 2n0+n1-1,由於完全二叉樹中度為1的結點數只有兩種可能0或1,由此得到n0=n/2 或 n0=(n+1)/2。簡便來算,就是 n0=n/2,其中n為奇數時(n1=0)向上取整;n為偶數時(n1=1)向下取整。可根據完全二叉樹的結點總數計算出葉子結點數。 查詢陣列中某個數的父結點和左右孩子結點,比如已知索引為i的數,那麼1.父結點索引:(i-1)/2(這裡計算機中的除以2,省略掉小數)2.左孩子索引:2i+13.右孩子索引:2i+2所以上面兩個陣列可以腦補成堆結構,因為他們滿足堆的定義性質:大根堆:arr(i)>arr(2i+1) && arr(i)>arr(2i+2)小根堆:arr(i)<arr(2i+1) && arr(i)<arr(2i+2)
優點 二叉排序樹是一種比較有用的折衷方案。陣列的搜尋比較方便,可以直接用下標,但刪除或者插入某些元素就比較麻煩。連結串列與之相反,刪除和插入元素很快,但查詢很慢。二叉排序樹就既有連結串列的好處,也有陣列的好處。在處理大批量的動態的資料是比較有用
缺點 缺點:順序儲存可能會浪費空間(在非完全二叉樹的時候),但是讀取某個指定的節點的時候效率比較高O(0)鏈式儲存相對二叉樹比較大的時候浪費空間較少,但是讀取某個指定節點的時候效率偏低O(nlogn) 最差時間也是nlogn 但是建立堆需要時間,
沒有快排好
記住 前序後序遍歷
            1                    二叉樹的性質  : 葉子結點個數為n0    , 度為1的個數為n1 , 度為2的個數 為n2
       /     邊  \                         n =   n0 + n1 + n2 ;//不是指一個,總數
   2               3                       邊 = n1 + 2  * n 2 //   頭結點上面啥都沒
 /     \                                    因為頭結點上面啥都沒,所以可以化為 n - 1
4      5                                   n -1 = n1+2 * n2  = n0 + n1 + n2 -1
                                                         ||
                                                        n0 = n2 + 1;
                         完全二叉樹的性質 : 度為 1 的 結點個數 為 0 和 1 
                             n0 = n2  + 1;   n = n0  + n1 + n2  ==> n = 2 n0 +n1 - 1 ;

判斷是否為完全二叉樹

import java.util.LinkedList;
import java.util.Queue;
/**********************************************************
* 非遞迴方法,基本是層次遍歷二叉樹 依次檢查每一個節點:
* 1.當發現有一個節點的左子樹為空,右子樹不為空時 直接返回false.
* 2.當發現有一個節點的左子樹不為空,右子樹為空時,置標誌位為1。
* 3.當發現有一個節點的左右子樹均為空時,置標誌位為1。
**********************************************************/
public class CompleteBinaryTree
{
    //檢查一棵樹是不是完全二叉樹  
    public boolean checking(TreeNode root)
    {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        boolean flag = false; // 葉子結點        TreeNode left;
        TreeNode right;
        queue.add(root);
        while (!queue.isEmpty()) {
            root = queue.poll();
            left = root.left;
            right = root.right;
            
            if ((flag && (left != null || right != null)) || (left == null && right != null)) {
                // 如果之前層遍歷的結點沒有右孩子,且當前的結點有左或右孩子,直接返回false
                // 如果當前結點有右孩子卻沒有左孩子,直接返回false
                return false;
            }
            
            if (left != null) queue.offer(root.left);
            
            if (right != null)queue.offer(root.right);
            else flag = true; // 如果當前結點沒有右孩子,那麼之後層遍歷到的結點必須為葉子結點            
        }
        return true;
    }
}
public static int getHigh(TreeNode root) {                 0         // 第一步,直接到3下面 判斷3的左右的結點為空,再走到下一步 再判斷 返回 1 
    if (root == null) return 0;                         /     \      // 第二步,返回到了1 判斷右邊 ,同樣道理 ,然後返回1 , 之後比較 加一後 返回到1結點的
    int leftHigh = getHigh(root.left);                 1       2     //值為2;
    int rightHigh = getHigh(root.right);             /   \    /  \   //依次
    return Math.max(leftHigh, rightHigh) + 1;       3     4  5    6  
}

BFS 和 DFS

DFS : 基本方法每層代表什麼狀態和需要多少層
BFS 和 DFS 區別一個層遍歷一個一頭紮下底的,
bfs

public static TreeNode Search (TreeNode root){
    //base case
    if (root==null)return null;


    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    TreeNode left;
    TreeNode right;
    while (!queue.isEmpty()){
        int stem = queue.size();
        for (int i = 0; i < stem; i++) {
           TreeNode a = queue.poll();
           if (a.left!=null){
               queue.add(a.left);
           }
           if (a.right!=null){
               queue.add(a.right);
           }
            System.out.print(a.val);
        }
        System.out.println();
    }
   return null;
}

判斷完全二叉樹

class Solution{
    public static boolean isComplementTree(TreeNode root){
       //base case
        if(root == null)return false;


        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode nodeLeft = null;
        TreeNode nodeRight = null;
        queue.add(root);
        boolean falg = false;
        while(!queue.isEmpty()){
           TreeNode node =  queue.poll();
           nodeLeft = node .left;
           nodeRight = node.right;
           if(falg&&(nodeLeft!=null||nodeRight!=null)||(nodeLeft==null&&nodeRight!=null)){
               return false;
           }
           if(nodeLeft!=null){
               queue.add(nodeLeft);
           }
           if (nodeRight!=null){
               queue.add(nodeRight);
           }else{
               falg = true;
           }
        }
        return  true;
    }
}

dfs

//題目:求abc可以任意取
class  Culotion{
    public static void findSubset(String[] str , int index , StringBuffer sbf){//取StringBuffer因為排列的順序
        if (index == str.length){                      //
           if (sbf.length() == 0){
               System.out.println("kong");
           }else {
               System.out.println(sbf.toString());
           }
           return;
        }
         sbf.append(str[index]);    //新增元素
        findSubset(str,index+1,sbf);      
        sbf.deleteCharAt(sbf.length() -1 ); //返回到上層
        findSubset(str,index+1,sbf);
    }
abc
ab
ac
a
bc
b
c
kong

//題目:給出數,求出多少對()的排序

 Dfs(3,0,0,s);
}
public static void Dfs(int n , int l , int r , StringBuffer s){
    if (l == n && r == n){            //左右邊等於其數時
        System.out.println(s);
        return;
    }
    if (l<n){              
        s.append("(");
        Dfs(n,l+1,r,s);
        s.deleteCharAt(s.length()-1);
    }
    if (r<l){               //如何判斷要不要加右邊,新增到左邊的( 要大於)才可以,不要數後面的
        s.append(")");
        Dfs(n,l,r+1,s);
        s.deleteCharAt(s.length() -1);
    }
}

//題目;求有25,10,5,1 來構成99的組合

public static void synthetic(int numerical , int level , int temp[]){
    if(level == 3){               
        temp[level] = numerical; //為一時候不需要迴圈直接列印了
        System.out.println(Arrays.toString(temp));
        return;
    }
    for (int i = 0 ; i <= numerical/coin[level] ; i++){    //用來分成的
         temp[level] = i;
        synthetic (numerical - coin[level]*i , level +1 , temp);
    }
}

//求排列組合,abc的組合

public static void jiaohuan(int index , String[] str,StringBuffer sbf ){
    if (index == 3){
        System.out.println(Arrays.toString(str));
        return;
    }
    for (int i = index ; i < str.length ; i++){   //一定要從index開始,因為去掉前面的定長
         swap(str,index,i);       
         jiaohuan(index + 1 ,str,sbf);
    }
}
public static String[] swap(String[] s , int index , int i){
    String temp ;
    temp = s[index];
    s[index] = s[i];
    s[i] = temp;
    return s;
public static void combination(String[] str , int level , StringBuffer sbf,boolean[] bl){
    if (level == 3){
        System.out.println(sbf);
        return;
    }
    for(int i = 0 ; i < str.length ; i++){
        if (bl[i] == false){
            sbf.append(str[i]);
            bl[i] = true;
            combination(str,level+1,sbf,bl);
            bl[i] = false;
            sbf.deleteCharAt(sbf.length() - 1);
        }
    }
}

可選不可選,for迴圈n叉樹,swap選擇重複的元素,組合多用

查目標數

1題目: 1   2    3    4
           5   6     7    8        找到目標數字6,判斷是否有
           9    10   11  12
//1. 二位陣列  [2][3] size = 12  index = 11;
   targer = 6     m = 4  n = 3
   left = 0;       right = n*m -1  - 1;   
 // mid = (l+r)/2 = 5       5/col = 5/4 = 1 ->row        5%col = 5%col = l  -> col //返回值的行和列
public  boolean  ifFind (int[][] matix ,int target){
    if(matix.length == null || matix[0].length == 0)return false;//判斷長度為0和陣列為空
     int row = matix.length; int  col = matix[0].length; // 二維陣列長度表示
     int i = 0; int  j = row * col -1;
   while(i<= j){//注意相等情況,當取一個數的時候
       mid = i + (j-i)/2;
        int  l = mid /col;
        int r = mid %col;
      if(matix[mid]==target){ 
           return ture;
         }else if(matix[mid] <target){
                 i = mid + 1;
          }else{
                  j = mid -1; 
          }
      }
     return false;
}
2題目;尋找一個數最近的數的下標 ;
l                     m                  t            r
****************************t*******
                      l             m    t           r
                      *************t*******
                                     l      t   m    r
                                     ****t*******
                                       l m r
                                        *t*
                                           lr   
                                           T*      //提前停下來,
targer==4    index             l = 2 r = 3
// e.g int      a[5] = {1   ,  2   ,3     ,8     ,9}
int binarySearch(int a[] ,int left ,int right ,int target){
    int  mid ;//不要重複定義
while(left < right -1){
    mid = left + (right - left)/2;
  if(arr[mid]==targer){    // 不需要滿足條件
           return mid ;
   } else if(arr[mid]<targer){
            left = mid ;        //left  = mid  +1 錯誤。因為如果正好是那個最近接那個容易跳過去
        }else{
             right = mid;
        }
 }

}
post  processing
 if(abs(arr[left] - targer ) <abs(arr[right] - targer){//判斷哪個更加接近
     return left;
}else {
 return right;
   }
3題目;e.g int  arr[]={2,5,5,5,5,5,5,,5,5,5,5,}  找出最左邊的 targer ;
if  targer = 5   return    1 返回下標    if     targer  = 10  retrun   -1;
當l和r相鄰的時候。跳出迴圈,在判斷哪個是最左的
int BinarySearch(int arr[] ,int target){                           
int mid ;
  while(left < right -1){
    mid = left +(right - left)/2;
if(arr[mid]==target){
    right = mid;                                                        //當題是最右邊的時候  left=mid
 }else if(arr[mid]<target){
     left = mid ;mid+1也可以,正好是他
      }else {
     right = mid;  //mid  -1 
    }
     }
}
if(arr[left] ==targer){//取出數值                     //righ        返回也是right
   return left;
 }else{
  return right ;
 }
//求出最近的那個數的最k的數字連起來的
List<Integer> list = new ArrayList<>();
if (Math.abs(arr[left] - target) < Math.abs(arr[right] - target)) {
left--;
while (left > 0 && right < arr.length && k > 0) {
list.add(arr[left]);
list.add(arr[right]);
k -= 2;
if (k == 1) {
if (arr[left] < arr[right]) {
left--;
list.add(arr[left]);
} else {
right++;
list.add(arr[right]);
}
}
}
return list;
} else {
right++;
while (left > 0 && right < arr.length && k > 0) {
list.add(arr[left]);
list.add(arr[right]);
k -= 2;
if (k == 1) {
if (left < right) {
left--;
list.add(arr[left]);
} else {
right--;
list.add(arr[right]);
}
}

}
return list;
}

byte 和Byte詳解

  1. :byte和Byte詳解
    byte是java的基本資料型別,儲存整型資料,佔據1個位元組(8 bits),能夠儲存的資料範圍是-128~+127。

Byte是java.lang中的一個類,目的是為基本資料型別byte進行封裝。

  1. :二者關係:
    Byte是byte的包裝類,就如同Integer和int的關係,

一般情況包裝類用於泛型或提供靜態方法,用於基本型別或字串之間轉換,建議儘量不要用包裝類和基本型別之間運算,因為這樣運算效率會很差的

Map相關

Map是java中的介面,Map.Entry是Map的一個內部介面。

         Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一個Set集合,此集合的型別為Map.Entry。

         Map.Entry是Map宣告的一個內部介面,此介面為泛型,定義為Entry<K,V>。它表示Map中的一個實體(一個key-value對)。介面中有getKey(),getValue方法。

下面是遍歷Map的四種方法:


public static void main(String[] args) {  
  
  
  Map<String, String> map = new HashMap<String, String>();  
  map.put("1", "value1");  
  map.put("2", "value2");  
  map.put("3", "value3");  
    
  //第一種:普遍使用,二次取值  
  System.out.println("通過Map.keySet遍歷key和value:");  
  for (String key : map.keySet()) {  
   System.out.println("key= "+ key + " and value= " + map.get(key));  
  }  
    
  //第二種  
  System.out.println("通過Map.entrySet使用iterator遍歷key和value:");  
  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();  
  while (it.hasNext()) {  
   Map.Entry<String, String> entry = it.next();  
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
  }  
    
  //第三種:推薦,尤其是容量大時  
  System.out.println("通過Map.entrySet遍歷key和value");  
  for (Map.Entry<String, String> entry : map.entrySet()) {  
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
  }  
  
  //第四種  
  System.out.println("通過Map.values()遍歷所有的value,但不能遍歷key");  
  for (String v : map.values()) {  
   System.out.println("value= " + v);  
  }  
 }  

一、整理:
看到array,就要想到角標。
看到link,就要想到first,last。
看到hash,就要想到hashCode,equals.
看到tree,就要想到兩個介面。Comparable,Comparator。
二、Map與Collection在集合框架中屬並列存在
1.Map儲存的是鍵值對
2.Map儲存元素使用put方法,Collection使用add方法
3.Map集合沒有直接取出元素的方法,而是先轉成Set集合,在通過迭代獲取元素
4.Map集合中鍵要保證唯一性
也就是Collection是單列集合, Map 是雙列集合。
總結:

  • Map一次存一對元素, Collection 一次存一個。Map 的鍵不能重複,保證唯一。
  • Map 一次存入一對元素,是以鍵值對的形式存在.鍵與值存在對映關係.一定要保證鍵的唯一性.

三、Map中常見方法:

1、新增:
1、V put(K key, V value) (可以相同的key值,但是新增的value值會覆
蓋前面的,返回值是前一個,如果沒有就返回null)
2、putAll(Map<? extends K,? extends V> m) 從指定對映中將所有對映關
系複製到此對映中(可選操作)。

2、刪除
1、remove() 刪除關聯物件,指定key物件
2、clear() 清空集合物件
3、獲取
1:value get(key); 可以用於判斷鍵是否存在的情況。當指定的鍵不存在的時候,返
回的是null。
4、判斷:
1、boolean isEmpty() 長度為0返回true否則false
2、boolean containsKey(Object key) 判斷集合中是否包含指定的key
3、boolean containsValue(Object value) 判斷集合中是否包含指定的value
5、長度:
Int size()

四、遍歷Map的方式:
1、將map 集合中所有的鍵取出存入set集合。
Set keySet() 返回所有的key物件的Set集合,再通過get方法獲取鍵對應的值。
2、 values() ,獲取所有的值.
Collection values()不能獲取到key物件
3、 Map.Entry物件 推薦使用 重點
Set<Map.Entry<k,v>> entrySet() 將map 集合中的鍵值對映關係打包成一個物件。
Map.Entry物件通過Map.Entry 物件的getKey,getValue獲取其鍵和值。

第一種方式:使用keySet
將Map轉成Set集合(keySet()),通過Set的迭代器取出Set集合中的每一個元素(Iterator)就是Map集合中的所有的鍵,再通過get方法獲取鍵對應的值。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo1 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);

//
// 獲取方法:
// 第一種方式: 使用keySet
// 需要分別獲取key和value,沒有面向物件的思想
// Set<K> keySet() 返回所有的key物件的Set集合
Set<Integer> ks = map.keySet();
Iterator<Integer> it = ks.iterator();
while (it.hasNext()) {
Integer key = it.next();
String value = map.get(key);
System.out.println("key=" + key + " value=" + value);
}
}
}

第二種方式: 通過values 獲取所有值,不能獲取到key物件

1 public static void main(String[] args) {
2 Map<Integer, String> map = new HashMap<Integer, String>();
3 map.put(1, "aaaa");
4 map.put(2, "bbbb");
5 map.put(3, "cccc");
6 System.out.println(map);
7 // 第二種方式:
8 // 通過values 獲取所有值,不能獲取到key物件
9 // Collection<V> values()10
11 Collection<String> vs = map.values();
12 Iterator<String> it = vs.iterator();
13 while (it.hasNext()) {
14 String value = it.next();
15 System.out.println(" value=" + value);
16 }
17 }

第三種方式: Map.Entry
public static interface Map.Entry<K,V> 通過Map中的entrySet()方法獲取存放Map.Entry<K,V>物件的Set集合。
Set<Map.Entry<K,V>> entrySet() 面向物件的思想將map集合中的鍵和值對映關係打包為一個物件,就是Map.Entry,將該物件存入Set集合,Map.Entry是一個物件,那麼該物件具備的getKey,getValue獲得鍵和值。

1 public static void main(String[] args) {
2 Map<Integer, String> map = new HashMap<Integer, String>();
3 map.put(1, "aaaa");
4 map.put(2, "bbbb");
5 map.put(3, "cccc");
6 System.out.println(map);
7 // 第三種方式: Map.Entry物件 推薦使用 重點
8 // Set<Map.Entry<K,V>> entrySet()
9
10
11 // 返回的Map.Entry物件的Set集合 Map.Entry包含了key和value物件12 Set<Map.Entry<Integer, String>> es = map.entrySet();
13
14 Iterator<Map.Entry<Integer, String>> it = es.iterator();
15
16 while (it.hasNext()) {
17
18 // 返回的是封裝了key和value物件的Map.Entry物件19 Map.Entry<Integer, String> en = it.next();
20
21 // 獲取Map.Entry物件中封裝的key和value物件22 Integer key = en.getKey();
23 String value = en.getValue();
24
25 System.out.println("key=" + key + " value=" + value);
26 }
27 }