剑指offer面试题笔记11~20题(Java实现)

一、面试题11:数值的整数次方(P90)

  题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,不需要考虑大数问题。

 解题思路:

 

二、面试题12:打印1到最大的n位数(P94)

  题目:输入数字n,按顺序打印出从1到最大的n为十进制数。比如输入3,则打印出1,2,3一直到999。

解题思路:

 

三、面试题13:在O(1)时间删除链表结点(P99)

  题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:

struct ListNode
{
    int m_nValue;
    ListNode* m_pNext
};

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted);

解题思路:获取待删除结点的下一个结点,将下一个结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除。若待删除结点是链表最后一个节点则需要从头到尾遍历。若链表中只有一个结点,删除结点后,还需要把链表的头结点设置为null。

 

public class T13 {
    public static void deleteNode (ListNode head, ListNode toDelete) {
        if (head == null || toDelete == null)
            return;
        
        if (toDelete.next != null) {
            ListNode next = toDelete.next;
            toDelete.value = next.value;
            toDelete.next = next.next;
            
            next = null;
        }
        else if (head == toDelete) {
            head = null;
            toDelete = null;
        }
        else {
            ListNode node = head;
            while (node.next != toDelete) {
                node = node.next;
            }
            node.next = null;
            toDelete = null;
        }
    }
}

 

 

 

 

四、面试题14:调整数组顺序使奇数位于偶数前面(P102)

  题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

解题思路:定义两个指针,一个从前往后,一个从后往前,前面指针若指向的是奇数,则向后移动,直到遇到偶数为止;后面指针若指向偶数,则向前移动,直到遇到奇数为止。当后面指针最终到前面指针之前时,终止。

 

public class T14 {
    public static void reorderOddEven (int[] num, int length) {
        if (num == null || length == 0)
            return;
        
        int begin = 0;
        int end = length - 1;
        
        while (begin < end) {
            while (num[begin] % 2 == 1)
                begin ++;
            while (num[end] % 2 == 0)
                end --;
            
            if (begin < end) {
                int temp = num[begin];
                num[begin] = num[end];
                num[end] = temp;
            }
        }
    }
}

 

 

 

 

五、面试题15:链表中倒数第K个结点(P107)

  题目:输入一个链表,输出该链表中倒数第K个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第一个结点。

  链表结点定义如下:  

struct ListNode
  {
    int m_nValue;
    ListNode* m_pNext;
  }

解题思路:定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;从第k步开始,第二个指针也开始从链表头指针开始遍历。由于两个指针距离保持在k-1,当第一个指针到达链表尾结点时,第二个指针正好是倒数第k个结点。

 

public class T15 {
    public static ListNode findKthToTail (ListNode node, int k) {
        ListNode ahead = node;
        ListNode behind = null;
        
        for (int i = 0; i < k - 1; i ++)
            ahead = ahead.next;
        
        behind = node;
        
        while (ahead.next != null) {
            ahead = ahead.next;
            behind = behind.next;
        }
        
        return behind;
    }
}

 

 

六、面试题16:反转链表(P112)

  题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。链表结点定义如下:


struct ListNode
  {
    int m_nValue;
    ListNode* m_pNext;
  }

 解题思路:

 

七、面试题17:合并两个排序的链表(P114)

  题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。  


struct ListNode
  {
    int m_nValue;
    ListNode* m_pNext;
  }

 解题思路:两个链表两个指针,链表值小的结点为头结点。指针后移,递归。

public static ListNode merge (ListNode head1, ListNode head2) {
        if (head1 == null)
            return head2;
        if (head2 == null)
            return head1;
        
        ListNode mergeHead = null;
        
        if (head1.value < head2.value) {
            mergeHead = head1;        
            mergeHead.next = merge (head1.next, head2);
        }
        else {
            mergeHead = head2;
            mergeHead.next = merge (head1, head2.next);
        }
        
        return mergeHead;
    }

 

八、面试题18:树的子结构(P117)

  题目:输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点定义如下:

struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode* m_pLeft;
    BinaryTreeNode* m_pRight;
}

解题思路:第一步在树A中查找与根结点的值一样的结点,实际上就是树的遍历。第二部是判断树A中以R为根结点的子树是不是和树B具有相同的结构。递归的终止条件是我们到达了树A或者树B的叶结点。

 

public static boolean hasSubTree (BinaryTreeNode root1, BinaryTreeNode root2) {
        boolean result = false;
        
        if (root1 != null && root2 != null) {
            if (root1.value == root2.value)
                result = doesTree1HaveTree2 (root1, root2);
            if (!result)
                result = hasSubTree (root1.left, root2);
            if (!result)
                result = hasSubTree (root1.right, root2);
        }
        
        return result;
    }
    
    public static boolean doesTree1HaveTree2 (BinaryTreeNode root1, BinaryTreeNode root2) {
        if (root2 == null)
            return true;
        
        if (root1 == null)
            return false;
        
        return doesTree1HaveTree2 (root2.left, root2.left) &&
                doesTree1HaveTree2 (root1.right, root2.right);
        
    }

 

 

 

九、面试题19:二叉树的镜像(P125)

  题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。

二叉树结点的定义如下:

struct BinaryTreeNode
{
    int m_nValue;
    BinaryTreeNode* m_pLeft;
    BinaryTreeNode* m_pRight;
}

解题思路:先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子结点。当交换完所有非叶子节点的左右子结点之后,就得到了树的镜像。

 

public static void mirrorRecursively (BinaryTreeNode node) {
        if (node == null || node.left == null || node.right == null)
            return;
        
        BinaryTreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
        
        if (node.left != null)
            mirrorRecursively(node.left);
        
        if (node.right != null)
            mirrorRecursively(node.right);
    }

 

 

十、面试题20:顺时针打印矩阵(P127)

  题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

则依次打印出数字:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10

解题思路:

posted @ 2014-11-15 22:48  Kevin__Chen  阅读(172)  评论(0)    收藏  举报