LZW演算法壓縮字串資料
連結串列
- 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(str1null||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
但是,二叉搜尋樹對雜湊表的效能很好:
- 二進位制搜尋樹永遠不會遇到衝突,這意味著二進位制搜尋樹可以保證在O(log(n))中實現插入,檢索和刪除,這比線性時間快得多。此外,樹所需的空間與輸入資料的大小完全相同。
- 您無需事先知道輸入大小。
- 對樹中的所有元素進行排序,以使有序遍歷花費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詳解
- :byte和Byte詳解
byte是java的基本資料型別,儲存整型資料,佔據1個位元組(8 bits),能夠儲存的資料範圍是-128~+127。
Byte是java.lang中的一個類,目的是為基本資料型別byte進行封裝。
- :二者關係:
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
2、 values() ,獲取所有的值.
Collection
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 }