java试题40例

0001 Singleton 单例模式

题目:设计一个类,我们只能生成该类的一个实例

参考答案

public class Singleton {

    private static Singleton singleton;

    // 注意点: 私有化构造函数
    private Singleton() {
    }

    // synchronized 多线程环境 
    public synchronized static Singleton getInsatnce() {
        if(singleton==null) {
            singleton = new Singleton();

        }       

        return singleton;
    }
}

0002 替换空格

题目:请实现一个函数,把字符数组中的每个空格替换成"%20"。如"I am javamm",输出为"I%20am%20javamm"

参考答案

/** 参考思路

 1. 遍历一次字符串得到空格的总数,以及数组的总长度

 2. 创建一个新字符数组长度为原字符串长度 + 空格个数 * 2

 3. 两个指针P1指向原字符数组末尾P2指向新字符数组的末尾 

 4. 移动P1,若非空格复制至新字符串数组,若为空格P2插入%20

分析

 时间复制度为O(n)
*/

0003 从尾到头打印链表

题目:输入一个链表,从尾到头打印出每个结点的值

参考答案

/**
 遍历链表至栈中,因为栈为后进先出*/

0004 重建二叉树

题目:输入一个二叉树的前序遍历和中序遍历的结果,请重建出该二叉树(假设不含有重复数字) 。如输入前序遍历{ 1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7,2,1,5,3,8,6}

0005 用两个栈实现队列

题目:用两个栈实现一个队列

0006 旋转数组的最小数字

题目:把一个数组的最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的一个旋转,输出旋转数组的最小元素。例如:{3,4,5,1,2} 为{1,2,3,4,5}的一个旋转,最小元素为1

参考答案

   // 二分查找 O(logn)

0006 斐波那契数列

题目:写一个函数,输入n,求Fibonacci数列的第n项

0007 二进制中1的个数

题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。如输入9,二进制为1001,输出结果为2

参考答案

/**
* 把一个整数减1之后再与原来的整数做位与运算得到的结果相当于是把整数的二进制表示中的最右边一个1变成0
*/

0008 数值的整数次方

题目:求数值的整数次方,不需要考虑大数的问题。

参考答案

// 代码需要完备
// 当指数为负数,底数为0等

0009 打印1到最大的n位数

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

参考答案

// 当n很大时,会溢出
// 可考虑用字符串表示数字

0010 在O(1)时间删除链表结点

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

参考答案

// 思路:把需删除结点的下一个结点内容复制到需删除的结点上,再把下一个结点删除

0011 调整数组顺序使奇数位于偶数前面

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

参考答案

/**
1. 维护两个指针P1指向数组的第一个数字向后移动; P2指向数组的最后一个数字向前移动2. 在指针相遇前若P1指向数字是偶数P2指向数字是奇数则交换这两个数字
3. 把比较的逻辑部分抽取出来实现解耦以满足更多的比较如把所有的负数放在非负数前面能被3整除的数放在不能被3整除的数前面
4. 代码扩展性可重用性
*/

0012 链表中倒数第K个结点

题目:输入一个单向链表,输出该链表中倒数第k个结点

/**
1. 两个指针P1,P2
2. P1从链表头向前遍历走k-1,P2不变
3. 第k步P1,P2一起移动当P1到达尾结点时P2正好是倒数第k个结点
*/

0013 求链表的中间结点

题目:如果链表中结点总数为奇数,返回中间结点;如果结点总数是偶数,返回中间两个结点的任意一个

/**
1. 类同0012定义两个指针P1,P2
2. 遍历链表P1走一步P2走两步当P2至达末尾时P1正好在链表的中间
*/

0014 判断一个单向链表是形成了环形结构

题目: 判断一个单向链表是形成了环形结构

1. 类同0013,定义两个指针P1,P2
2. 历链表,P1走一步,P2走两步,如果走的快的追上了走的慢的,则为环形链表
3. 如果P2走到了链表末尾,仍没有追上P1,则不是环形链表

0015 反转链表

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

/**
* 为防止链表断开需要保存结点
*/

0016 合并两个排序的链表

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

0017 树的子结构

题目:输入一棵二叉树A和B,判断B是不是A的子结构。

0018 二叉树的镜像

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

```Java /* 前序遍历树的每个结点 * 如果遍历到的结点有子结点,则交换子结点 * 当交换完所有非叶子结点的左右子结点后,就得到了树的镜像 */ public void mirrorRecursively(BinaryTreeNode binaryTreeNode) { if(binaryTreeNode==null || (binaryTreeNode.leftNode==null && binaryTreeNode.rightNode==null) ) { return; }

BinaryTreeNode tempNode=binaryTreeNode.leftNode;
binaryTreeNode.leftNode=binaryTreeNode.rightNode;
binaryTreeNode.rightNode=tempNode;

// 递归
mirrorRecursively(binaryTreeNode.leftNode);
mirrorRecursively(binaryTreeNode.rightNode);        

# 0019 包含min函数的栈 ## 题目:定义栈的数据结构,实现一个得到栈最小值的min函数。使得调用min,push及pop的时间复杂度都为O(1). ## 参考答案Java /* 采用辅助栈,将最小值压入辅助栈中 */ ```

0020 栈的压入,弹出序列

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字都不相等。如序列1,2,3,4,5为压栈序列,序列4,5,3,2,1为该压栈序列对应的一个弹出序列,但4,3,5,1,2不是该压栈序列的弹出序列

/**
* 如果下一个弹出的数字刚好是栈顶数字直接弹出
* 如果下一个弹出的数字不在栈顶把压栈序列中还没有入栈的数字压入辅助栈直到把下一个需要弹出的数字压入栈顶为止
* 如果所有的数字都压入栈了仍然没有找到下一下弹出的数字那么该序列不可能是一个弹出序列
*/

0031 归并排序MergeSort

题目:请写出归并排序

参考答案

```Java package com.javamm.al.sort;

/** * * 算法复杂度O(nlogn),冒泡,插入,选择都需要O(n2),若n为10000,n平方100000000,nlogn为40000,若归并需要40s, * 则插入排序需要28h 缺点:需要在存储器有另一个大小等于被排序的数据项目的数组,即要足够的空间 思想:归并两个有序的数组 * 注意:类名请写成MergeSort */ public class MergeSort {

public static void recSort(int[] data, int left, int right) {

    System.out.println("recSort,left:" + left + " right:" + right);

    if (left == right) {

        return;
    }

    int center = (left + right) / 2;

    // 递归左边
    recSort(data, left, center);

    // 递归右边
    recSort(data, center + 1, right);

    // merge
    merge(data, left, center, right);

}

public static void merge(int[] data, int left, int center, int right) {

    System.out.println("merge,left:" + left + " center: " + center
            + " right: " + right);

    int[] tmpData = new int[data.length];
    int mid = center + 1;
    int third = left;
    int tmp = left;
    while (left <= center && mid <= right) {
        if (data[left] <= data[mid]) {
            tmpData[third++] = data[left++];
        } else {
            tmpData[third++] = data[mid++];
        }
    }

    while (mid <= right) {
        tmpData[third++] = data[mid++];
    }

    while (left <= center) {
        tmpData[third++] = data[left++];
    }

    // 将tmpData中的内容复制回原数组
    while (tmp <= right) {
        data[tmp] = tmpData[tmp++];
    }
}

public static void main(String[] args) {

    int[] data = { 3, 2, 1, 6, 0, 8 };

    recSort(data, 0, data.length - 1);

    for (int i = 0; i < data.length; i++) {
        System.out.print(data[i] + " ,");
    }
}

# 0032 QuickSort ## 请写出快速排序 ## 参考答案Java /* 思想: * 1. 一躺排序将要排序的数据分成独立的两部分,一部分比另一部分所有数据都小,可用两指针,leftP,rightP,分别指向首尾 * 2. 再按此方法对这两部分数据进行排序,可用递归 * * 算法复杂度: * * 最坏情况算法复杂度:O(n2),最好O(nlogn) */ public class QuickSort {

private static int[] a;

public static void main(String[] args) {
    a = new int[] { 5, 3, 2, 1, 8, 4 };
    recQuickSort(0, a.length - 1);
    display();
}

public static void recQuickSort(int left, int right) {
    // Step 1 :把数组划分成左边和右边,左边比选定的值小,右边比选定的值大
    // Step 2 : 递归调用左边
    // Step 3 : 递归调用右边
    if (left >= right) {
        return;
    }

    int pivot = a[right];
    int partition = partitionIt(left, right, pivot);
    recQuickSort(left, partition - 1);
    recQuickSort(partition + 1, right);
}

public static int partitionIt(int left, int right, int pivot) {
    display();

    // 左指针
    int leftP = left - 1;

    // 右指针
    int rightP = right;

    while (true) {

        // 左边的值都比pivot小时
        while (a[++leftP] < pivot)
            ;

        // 右边的值都比pivot大时
        while (rightP > 0 && a[--rightP] > pivot)
            ;

        if (leftP >= rightP) {
            break;
        } else {
            // 交换
            swap(left, right);
        }
    }
    swap(leftP, right);
    return leftP;
}

public static void swap(int left, int right) {
    int temp = a[left];
    a[left] = a[right];
    a[right] = temp;
}

public static void display() {
    for (int i = 0; i < a.length; i++) {
        System.out.print(a[i] + " ");
    }
    System.out.println("");
}

}

```

0033 HeapSort

参考答案

/**
*
* 若一个数组节点的索引为x
* 
* 其父节点的下标为(x-1)/2
* 
* 左子节点下标为2*x +1
* 
* 右子节点下标为2*x + 2
*
*/

层次遍历二叉树

题目:写一个函数,层次遍历二叉树

参考答案

/**
* 思路每打印一个结点的时候如果该结点有子结点将子结点放入队列末尾
*/

字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列。如输入abc,则输出acb,bac,bca,cab,cba

参考答案

Java /** * 将字符串分为两部分,一部分是字符串的第一个字符,另一部分是第一个字符外所有字符 * 用递归 */ # 字符串的所有组合 ## 题目:输入一个字符串,打印出该字符串中字符的所有组合。如输入abc,则输出a,b,c,ab,ac,bc,abc,注,ab,ba是不同的排列,但只算一个组合 Java /** * 输入n个字符,则能构成长度为1,2,...n的组合 * 求n个字符长度为m的组合的时候,把m个字符分为两部分,第一个和m-1个,递归 */ # 正方体所有面之和相等 ## 输入一个含有8个数字的数组,判断有没有可能这8个数字分别放到正方体的8个顶点上,使得每一面的顶点之和都相等。 Java /** * 如输入a1,a2,a3,a4,a5,a6,a7,a8,求所有排列,看是否满足条件,a1+a2+a3+a4==a5+a6+a7+a8,a1+a3+a5+a7=a2+a4+a6+a8,并且a1+a2+a5+a6=a3+a4+a7+a8 */ # 0029 数组中出现次数超过一半的数字 ## 题目:数组中有一个数字出现的次数超过了数组长度的一半,请求出这个数字。如{1,2,3,2,2,2,5,4,2},此数字为2 Java /** * 思路一:排序,排好序后,求中间数字 * 根据快排思想,先随机选一个数字,使比他小的都排在左边,比他大的都排右边。完成后,若此数字下标为n/2,即为此数。如果下标> n/2,那么此数位于左边,可在左半部查找,用递归。否则位于右边 * 思路二: * 遍历数组时,保存两个值,一个为数组中数字,一个为次数 * 当遍历下一个数字时,若与保存数字相同,次数+1.若与保存数字不同,次数-1,若次数=0,重新保存新数字,并将次数设为1.最后一次把次数设为1的数字即为所需的数字 * eg: * 1,1 * 2,1 * 3,1 * 2,1 * 2,2 * 2,3 * 2,2 * 2,1 * 2,2 */ # 0030 求一个数组的第k小的数 ## 题目:给定一个无序整数数组,返回这个数组中第k小的数 ```Java /* 思路一: * 最平常的思路是将数组排序,最快的排序是快排,然后返回已排序数组的第k个数,算法时间复杂度为O(nlogn),空间复杂度为O(1)。使用快排的思想,但是每次只对patition之后的数组的一半递归,这样可以将时间复杂度将为O(n)。

  • 具体的思路:将数组按照第一个数字first进行划分,将比first小的放在左边,比first大的放在右边,first放中间。返回patition之后first的下标j。如果此时j+1==k(+1是因为数组下标从0开始)那么说明a[j]就是要找的第k个数。如果j+1k,递归查找右半部分

* * 思路二: * 维持一个大小为k的大顶堆,遍历一次数组,如果数组中的元素比堆顶的元素小,那么就更新堆。最后堆中存放的是数组中的前k小元素。堆顶元素即为要求的第k小个数。

  • 这种算法不需要改变原数组结构,但是需要额外维持一个大小为O(k)的堆,时间复杂度为(nlogk)。当k比n小的多的时候,这个算法也是一个很好的选择 /* # 0031 连续子数组的最大和 ## 题目:输入一个整数型数组,数组中有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值Java /**
  • 思路一:列举数组规律
  • 维护一个最大值max
  • 若max < 0 ,抛弃
  • 若 > max ,更新max *
  • 思路二:动态规划
  • f(i)表示以第i个数字结尾的子数组的最大和,0<=i<n,有如下公式
  • f(i) = data[i], i=0或f(i-1)<=0
  • f(i) = f(i-1) + data[i] i!=0 && f(i-1) > 0 */ ``` # 0032 从1到n整数中1出现的次数 ## 题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。eg: 输入12,包含1的数字,1,10,11,12,共出现了5次

0033 把数组排成最小的数

题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。eg输入数组{3,32,321} ,则打印这3个数字排成的最小数字321323


你可能感兴趣的:(java试题40例)