Java面试题-算法篇十七

简介: Java面试题-算法篇十七

170,堆和栈在内存中的区别是什么?


概念:


       栈(stack)是为执行线程留出的内存空间。当函数被调用的时候,栈顶为局部变量和一些 bookkeeping 数据预留块。当函数执行完毕,块就没有用了,可能在下次的函数调用的时候再被使用。栈通常用后进先出的方式预留空间;因此最近的保留块通常最先被释放。这么做可以使跟踪堆栈变的简单;从栈中释放块只不过是指针的偏移而已。


       堆(heap)是为动态分配预留的内存空间。和栈不一样,从堆上分配和重新分配块没有固定模式;你可以在任何时候分配和释放它。这样使得跟踪哪部分堆已经被分配和被释放变的异常复杂;有许多定制的堆分配策略用来为不同的使用模式下调整堆的性能。


区别:

       内存分配:

           栈:由编译器自动分配和释放,存放函数的参数、局部变量、临时变量、函数返回地址等。


           堆:一般人为分配和释放,对Java而言由系统释放回收,但对于C++等,必须手动释放,如果没有手动释放会引起内存泄漏。

     


系统响应:


           栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出。


          堆:在记录空闲内存地址的链表中寻找一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。

       


大小限制:


          栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 windows下,栈的大小是2M,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。


          堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。


结论:堆获得的空间比较灵活,也比较大。

     


分配效率:


          栈:由系统自动分配,速度较快,无法人为控制。


          堆:由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。


      存储内容:


          栈:在栈中,第一个进栈的是主函数下一条指令的地址,然后是函数的各个参数,在大多数编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意,静态变量不入栈。出栈则刚好顺序相反。


      堆:一般在堆的头部用一个字节存放堆的大小,具体内容受人为控制。


171,求出1000之内的所有水仙花数


概念:


水仙花数指的是一个三位整数,它的各位数字的立方和等于这个数本身.。


解法:


public class NumberOfDaffodils {    
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
         int hundred, ten, bits;    
         System.out.println("水仙花数为:");    
         for (int i = 100; i <= 999; i++)    
         {    
             hundred = i / 100;    
             ten = i % 100 / 10;    
             bits = i % 10;    
             if (i == hundred * hundred * hundred + ten * ten * ten + bits * bits * bits)    
             {    
                 System.out.print(i + "    ");    
             }    
         }      
    }  
}


172,比较一下几种常用的排序算法,简单的写一下你知道的几种排序算法?


比较:


1.稳定性比较

        插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的

       选择排序、希尔排序、快速排序、堆排序是不稳定的


2.时间复杂性比较

       插入排序、冒泡排序、选择排序的时间复杂性为O(n2)

       其它非线形排序的时间复杂性为O(nlog2n)

       线形排序的时间复杂性为O(n);


3.辅助空间的比较

       线形排序、二路归并排序的辅助空间为O(n);

       其它排序的辅助空间为O(1);


4.其它比较

       *插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度,但是在这种情况下,快速排序反而慢了。

       *当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。

       *若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。

       *当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。

       *当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下宜用归并排序。

       *当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。


常见的排序算法:


选择排序

public class SelectionSort {
    public void selectionSort(int[] array) {
       int temp;
       for (int i = 0; i < array.length - 1; i++) {
              for (int j = i + 1; j <= array.length - 1; j++) {
              if (array[i] > array[j]) {    
              // 注意和冒泡排序的区别,这里是i和j比较。
              temp = array[i];
              array[i] = array[j];
              array[j] = temp;
             }
        }            // 打印每趟排序结果
       for (int m = 0; m <= array.length - 1; m++) {
             System.out.print(array[m] + "\t");
       }
          System.out.println();
       }
    }    
    public static void main(String[] args) {
        SelectionSort selectionSort = new SelectionSort(); 
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        selectionSort.selectionSort(array);        
    for (int m = 0; m <= array.length - 1; m++) {
            System.out.print(array[m] + "\t");
        }
    }
}



插入排序

public class InsertSort {
    public void insertSort(int[] array, int first, int last) {        
    int temp, i, j;        
    for (i = first + 1; i <= last - 1; i++) {
            temp = array[i];
            j = i - 1;            
        while (j >= first && array[j] > temp) {
                array[j + 1] = array[j];
                j--;
            }
            array[j + 1] = temp;            // 打印每次排序结果
            for (int m = 0; m <= array.length - 1; m++) {
                System.out.print(array[m] + "\t");
            }
            System.out.println();
        }
    }    
     public static void main(String[] args) {
        InsertSort insertSort = new InsertSort();
            int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        insertSort.insertSort(array, 0, array.length);      
             for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
    }
}



快速排序

public class QuickSort {    
    public int partition(int[] sortArray, int low, int height) {        
    int key = sortArray[low];        
    while (low < height) {            
        while (low < height && sortArray[height] >= key)
            height--;
            sortArray[low] = sortArray[height];            
            while (low < height && sortArray[low] <= key)
                low++;
                sortArray[height] = sortArray[low];
            }
            sortArray[low] = key;        // 打印每次排序结果
        for (int i = 0; i <= sortArray.length - 1; i++) {
            System.out.print(sortArray[i] + "\t");
        }
        System.out.println();        
        return low;
    }    
    public void sort(int[] sortArray, int low, int height) {        
        if (low < height) {            
            int result = partition(sortArray, low, height);
            sort(sortArray, low, result - 1);
            sort(sortArray, result + 1, height);
        }
    }
    public static void main(String[] args) {
        QuickSort quickSort = new QuickSort();        
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };        
        for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
        quickSort.sort(array, 0, 8);        
        for (int i = 0; i <= array.length - 1; i++) {
            System.out.print(array[i] + "\t");
        }
    }
}


希尔排序

public class ShellSort {
    public void shellSort(int[] array, int n) {
        int i, j, gap;
        int temp;
        for (gap = n / 2; gap > 0; gap /= 2) {
            for (i = gap; i < n; i++) {       
                for (j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap) {
                    temp = array[j];
                    array[j] = array[j + gap];
                    array[j + gap] = temp;
                }                // 打印每趟排序结果
                for (int m = 0; m <= array.length - 1; m++) {
                    System.out.print(array[m] + "\t");
                }
                System.out.println();
            }
        }
    } 
     public static void main(String[] args) {
        ShellSort shellSort = new ShellSort();
        int[] array = { 5, 69, 12, 3, 56, 789, 2, 5648, 23 };
        shellSort.shellSort(array, array.length);        
        for (int m = 0; m <= array.length - 1; m++) {
            System.out.print(array[m] + "\t");
        }
    }
}



就先列到这里了,谁还有其他算法的示例或者有这些算法的其他更优解,欢迎留言讨论!


Java知音公众号推送Java开发中的一些必备技能,包括但不限于数据库、Java核心、流行框架、管理工具以及服务器相关,同时为您精选流行的开源项目,必会的面试选题,练手项目,优质视频资源等。让您闲暇之余巩固一下自己的知识,不知不觉中提高自己的开发水

相关文章
|
3月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
148 0
|
2月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
293 0
|
3月前
|
存储 安全 Java
常见 JAVA 集合面试题整理 自用版持续更新
这是一份详尽的Java集合面试题总结,涵盖ArrayList与LinkedList、HashMap与HashTable、HashSet与TreeSet的区别,以及ConcurrentHashMap的实现原理。内容从底层数据结构、性能特点到应用场景逐一剖析,并提供代码示例便于理解。此外,还介绍了如何遍历HashMap和HashTable。无论是初学者还是进阶开发者,都能从中受益。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
173 4
|
3月前
|
存储 安全 Java
2025 最新史上最全 Java 面试题独家整理带详细答案及解析
本文从Java基础、面向对象、多线程与并发等方面详细解析常见面试题及答案,并结合实际应用帮助理解。内容涵盖基本数据类型、自动装箱拆箱、String类区别,面向对象三大特性(封装、继承、多态),线程创建与安全问题解决方法,以及集合框架如ArrayList与LinkedList的对比和HashMap工作原理。适合准备面试或深入学习Java的开发者参考。附代码获取链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
561 48
|
2月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
|
3月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
82 5
|
3月前
|
Java API 微服务
2025 年 Java 校招面试全攻略:从面试心得看 Java 岗位求职技巧
《2025年Java校招最新技术要点与实操指南》 本文梳理了2025年Java校招的核心技术栈,并提供了可直接运行的代码实例。重点技术包括: Java 17+新特性(Record类、Sealed类等) Spring Boot 3+WebFlux响应式编程 微服务架构与Spring Cloud组件 Docker容器化部署 Redis缓存集成 OpenAI API调用 通过实际代码演示了如何应用这些技术,如Java 17的Record类简化POJO、WebFlux构建响应式API、Docker容器化部署。
108 5
|
3月前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
146 6
|
3月前
|
安全 Java API
2025 年 Java 校招面试常见问题及详细答案汇总
本资料涵盖Java校招常见面试题,包括Java基础、并发编程、JVM、Spring框架、分布式与微服务等核心知识点,并提供详细解析与实操代码,助力2025校招备战。
139 1
|
3月前
|
算法 Java 微服务
2025 年 Java 面试宝典社招春招秋招实操全方位攻略
2025年Java面试宝典涵盖核心技术及最新趋势,分为四大板块:1. Java基础:深入数据类型、多态等特性,结合学生信息管理等实例;2. JVM核心:解析内存模型与GC算法,附多线程转账等场景应用;3. 高并发方案:详解synchronized与线程池配置,提供Web服务器优化案例;4. Spring生态:剖析IoC/AOP原理,演示微服务架构实现。特别新增Java 17+特性实操,包括Record类、密封接口等语法糖,整合Spring Boot 3、响应式编程及云原生技术,通过订单状态机、API网关配置。
196 1

热门文章

最新文章