剑指offer(Java实现)

02、实现Singleton模式



03、二维数组中的查找

public static boolean findInPartiallySortedMatrix(int[][] array, int targetNumber) {
		int row = array.length;
		int col = array[0].length;
		
		int i = 0, j = col - 1;
		
		while (i < row && j >= 0) {
			if (array[i][j] > targetNumber) {
				j--;
			} else if (array[i][j] < targetNumber) {
				i++;
			} else return true;
		}
		return false;		
	}


04、替换空格

str.replace( "   " "" ); 


05、从尾到头打印链表

    public static void printListReversingly_Iteratively(Node head) {
		if (head == null) {
			return;
		}
		
		stack<Node> nodes = new stack<Node>();
		while (head != null) {
			nodes.push(head);
			head = head.next;
		}
		while (!nodes.isEmpty) {
			System.out.println(nodes.pop().value);
		}
	}
	
    public static void printListReversingly_Recursively(Node head) {
		if (head != null) {
			if (head.next != null) {
				printListReversingly_Recursively(head.next);			
		    } else System.out.println(head.value);
		}
	}


06、重建二叉树

根据先序遍历序列和中序遍历序列重建二叉树
        public TreeNode reConstructBinaryTree(int[] preOrder,int[] inOrder) {
		if (preOrder.length != inOrder.length) throws Exception;
		int index = preOrder.length - 1;
		if (index == 0) return null;
		return reConstructBinaryTree(preOrder, 0, index, inOrder, 0, index);
	}
	private TreeNode reConstructBinaryTree(int[] preOrder,int preStart, int preEnd, int[] inOrder, int inStart, int inEnd) {
		if (preStart > preEnd || inStart > inEnd)
			return null;
			
		TreeNode root = new TreeNode(preOrder[preStart]);
		
		for (int i = inStart; i <= inEnd; i++) {
			if (inOrder[i] == preOrder[preStart]) {
				root.left = reConstructBinaryTree(preOrder, preStart + i - inStart, index, inOrder, inStart, i - 1);
				root.right = reConstructBinaryTree(preOrder, preStart + i - inStart + 1, preEnd, inOrder, i + 1, inEnd);
			}
		}
		return root;
	}


07、用两个栈实现队列

        private Stack<Item> appendStack = new Stack<Item>(); 
	private Stack<Item> deleteStack = new Stack<Item>(); 
	
	public void appendTail(Item item) {
		appendStack.push(item);
	}
	public item deleteHead() {
		
		if (deleteStack.isEmpty()) {
			while(!appendStack.isEmpty()) {
				deleteStack.push(appendStack.pop());
			}
		}
		if (deleteStack.isEmpty())
			throws new Exception("队列为空,不能删");
		return deleteStack.pop();
	}


08、旋转数组的最小数字

借鉴二分查找法
	public int minInReversingList(int[] numbers) {
		if(numbers == null)
			throws new Exception("数组为空"):
		
		int index1 = 0;
		int index2 = numbers.length - 1;
		int indexMid = (index1 + index2) / 2;
		
		while (numbers[index1] >= numbers[index2]) {
			if (index2 - index1 == 1) {
				indexMid = index2;
				break;
			}
			
			if (numbers[index1] == numbers[index2] || numbers[indexMid] == numbers[index2])
				return minInOrder(numbers, index1, index2);
			
			if (numbers[indexMid] >= numbers[index1]) {
				index1 = indexMid;
			} else if(numbers[indexMid] <= numbers[index2]) {
				index2 = indexMid;
			}
		}
	}
	private int minInOrder(int[] arr, int startIndex, int endIndex) {
		int result = numbers[startIndex];
		for (int i = startIndex; i <= endIndex; i++) {
			if (numbers[i] < result)
				result = numbers[i];
		}
		return result;
	}


09、斐波那契数列求和

调用递归效率低下,因此选择从下往上计算。拓展:青蛙跳台阶。
	public int fibonacciNormal(int n) {
		if (n < 0)
			throws new Exception("n 必须 >= 0");
		
		int[] result = {0, 1};
		if (n < 2) return result[n];
		
		int n1 = 1, n2 = 1, sn = 0;  
        for(int i = 2; i < n; i++) {  
            sn = n1 + n2;  
            n1 = n2;  
            n2 = sn;  
        }  
        return sn;		
	}


10、二进制中1的个数

除法效率低下,尽量使用与运算。右移数字i并判1,如果遇到负数会陷入死循环。因此左移1,依次与运算。
	public int countOfNumberOne_1(int number) {
		int count = 0;
		int flag = 1;
		while(flag != 0) {
			if(number & flag != 0)
				count++;
			flag << 1;
		}
		return count;
	}
	public int countOfNumberOne_1(int number) {
		int count = 0;
		while (num != 0) {  
          	  count++;  
         	   num = num & (num - 1);    
     		  }
		return count;
	}




DAY 2    2017/3/28

11、数值的整数次方

    public double pow(double base, int exponent) {
        if (exponent == 0)
            return 1;
        if (exponent<0) {
            exponent = - exponent;
            base = 1/base;                   //数学上规定n个a相乘表示为a×a×a×a×...=a^n,其中 a≠0。
        }
        return (exponent % 2 == 0) ? pow(base*base, exponent >> 1) : base*pow(base*base, exponent >> 1);    //右移比除法效率高
    }

12、打印1到最大的n位数

当输入n很大的时候,我们求最大的n位数是不是用整型(int)或者长整型(long long)都会溢出?也就是说我们需要考虑大数问题。最常用的也是最容易的用字符串或者数组表达大数。

public void print1ToMaxOfNDigits(int n) {
        if (n <= 0) { 
            System.out.println("输入出错!");  
			return;
		}
		
        int[] number = new int[n];  
        while (!increment(number)) { 
            print(number); 
        }
	}
	private boolean increment(int[] number) {  
        boolean isOverflow = false;  
        int nTakeOver = 0;          // 进位  
		
        for (int i = number.length - 1; i >= 0; i--) { 			
            int nSum = number[i] + nTakeOver;		//nTakeOver使用一次后即跳出循环,不用清零
           
            if (i == number.length - 1)            // 如果是最低位加1  
                nSum++;  			
            if (nSum >= 10) {  
                if (i == 0)  
                    isOverflow = true;  
                else {  
                    nTakeOver = 1;  
                    number[i] = nSum - 10;  
                }  
            } else {  
                number[i] = nSum;  
                break;                       // 最低位加1后有进位会循环改变前面的位,没有进位跳出循环,前面的位不变                 
            }  
        }  
        return isOverflow;  
    }    
    // 打印一个数,循环遍历数组,从不为0的位开始打印  
    private void print(int[] number) {  
	
        boolean isValid = false;  
        for (int i = 0; i < number.length; i++) {  
            if (!isValid && number[i] != 0)  
                isValid = true;
            if (isValid)
                System.out.print(number[i]);
        }
		System.out.println();
    } 


13、O(1)时间删除链表节点

public void deleteNode(ListNode head, ListNode deListNode){  
        if (deListNode == null || head == null) 
            return;  
			
		if (deListNode.next != null){                     //要删除的不是尾节点
			deListNode.data = deListNode.next.data;  
            deListNode.next = deListNode.next.next; 
		} else if (head == deListNode) {                  //只有一个节点,删除头(尾)结点
			head = null;
		} else {                                          //有多个节点,删除尾结点
			ListNode pinitListNode = head;  
            while (pinitListNode.next.next != null) {  
                pinitListNode = pinitListNode.next;  
            }  
            pinitListNode.next = null;
		}		
    }


14、调整数组使奇数位于前面

	public void reorderArray(int[] array) {
		
		if (array == null) return;
		
		int pLeft = 0;
		int pRight = array.length - 1;
		while (pLeft < pRight) {
			while (pLeft < pRight && isOdd(array[pLeft])) {
				pLeft++;
			}
			while (pLeft < pRight && !isOdd(array[pRight])) {
				pRight--;
			}
			
			if (pLeft < pRight) {
				int temp = array[pLeft];
				array[pLeft] = array[pRight];
				array[pRight] = temp;
			}			
		}
	} 
	private boolean isOdd(int num) {
		return num % 2 != 0;
	}

15、链表中倒数第K个节点

	public ListNode findKthToTail(ListNode head, int k) {
		if (head == null || k <= 0)
			return null;
		
		ListNode pAhead = head, pBehind;
		for (int i = 0; i < k - 1; i++) {
			if (pAhead.next != null) {
				pAhead = pAhead.next;
			} else return null;
		}
		
		pBehind = head;
		while (pAhead.next != null) {
			pAhead = pAhead.next;
			pBehind = pBehind.next;
		}
		return pBehind;
	}


16、反转链表

	public ListNode reverseListNode(ListNode head) {  	
		ListNode pPrev = null, pNode = head;	
		while (pNode != null) {
		
			ListNode pNext = pNode.next;		
			pNode.next = pPrev;
		
			pPrev = pNode;
			pNode = pNext;
		}
		return pPrev;
	}

17、合并两个排序的链表

public ListNode mergeSortedListNode(ListNode pHead1, ListNode pHead2) {
		if (pHead1 == null) return pHead2;  
        else if (pHead2 == null) return pHead1;
		
		ListNode pMergedHead = null;
		if (pHead1.value < pHead2.value){  
            pMergedHead = pHead1;  
            pMergedHead.next = Merge(pHead1.next, pHead2);  
        }else{  
            pMergedHead = pHead2;  
            pMergedHead.next = Merge(pHead1, pHead2.next);  
        }  
        return pMergedHead;  
	}

18、树的子结构

分两步:第一步在树A中找到和B的根节点的值一样的结点R,第二步再判断树A中以R为根结点的子树是不是包含和树B一样的结构。
	public boolean isSubtree(Node root1, Node root2) {
		if (root2 == null) return true;
		if (root1 == null) return false;
		return equals(root1, root2) || isSubtree(root1.left, root2) || isSubtree(root1.right, root2);
	}
	private boolean equals(Node root1, Node root2) {
		if (root2 == null) return true;
		if (root1 == null) return false;
		if (root1.data != root2.data) return false;         // Should use .equals if Node.data isn't primitive
		return equals(root1.left, root2.left) && equals(root1.right, root2.right);
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值