查看原文
其他

随机算法,四大组件,Context,线程间通信,数组和链表

码仔 码个蛋 2019-08-28


码仔,今天就给大家带来了《每日一道面试题》的第七期:


01

随机算法 



问题:从扑克牌中随机抽 5 张牌,判断是不是顺子,即这 5 张牌是不是连续的。2-10 为数字本身,A 为 1,J 为 11,Q 为 12,K 为 13,而大小王可以看成任意的 数字

解题思路:我们可以把5张牌看成是由5个数字组成的数组。大小王是特殊的数字,我们可以把它们都定义为0,这样就可以和其他的牌区分开来。

首先把数组排序,再统计数组中0的个数,最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺的总数小于或者等于0的个数,那么这个数组就是连续的,反之则不连续。如果数组中的非0数字重复出现,则该数组是不连续的。换成扑克牌的描述方式就是如果一幅牌里含有对子,则不可能是顺子。

import java.util.Arrays;

public class Solution {

public boolean isContinuous(int[] number){
if(number == null){
return false;
}
Arrays.sort(number);
int numberZero = 0;
int numberGap = 0;
//计算数组中0的个数
for(int i = 0;i < number.length && number[i] == 0; i++){
numberZero++;
}
//统计数组中的间隔数目
int small = numberZero;
int big = small + 1;

while(big<number.length){
//两个数相等,有对子,不可能是顺子
if(number[small] == number[big]){
return false;
}
numberGap+= number[big] - number[small] - 1;
small = big;
big++;
}

return (numberGap>numberZero)?false:true;
}
}




02

简述四大组件


Activity、Service、ContentProvider 如 果 要 使 用 则 必 须 在AndroidManifest.xml 中 进 行 注 册 , 而BroadcastReceiver则有两种注册方式,静态注册和动态注册。其中静态注册就是指在AndroidManifest.xml中进行注册,而动态注册时通过代码注册。

Activity:通常展现为一个用户操作的可视化界面。它为用户提供了一个完成操作指令的窗口。 (https://mp.weixin.qq.com/s/CgfeMT9YtzW2jBavG47i1Q) (Activity的来由)

Service:Android系统的服务(不是一个线程,是主程序的一部分),与Activity不同,它是不能与用户交互的,不能自己启动的,须要调用Context.startService()来启动,执行后台,假设我们退出应用时,Service进程并没有结束,它仍然在后台行。

BroadcastReceiver:广播接收器是一个专注于接收广播通知信息,并做出相应处理的组件。

ContentProvider:(内容提供者)主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其它应用訪问,其它应用能够通过ContentProvider对指定应用中的数据进行操作。




03

谈谈对Android中context的理解 


Context是一个抽象基类。在翻译为上下文,也可以理解为环境,是提供一些程序的运行环境基础信息。Context下有两个子类,ContextWrapper是上下文功能的封装类,而ContextImpl则是上下文功能的实现类。而ContextWrapper又有三个直接的子类, ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity,所以Activity和Service以及Application的Context是不一样的,只有Activity需要主题,Service不需要主题。Context一共有三种类型,分别是Application、Activity和Service。这三个类虽然分别各种承担着不同的作用,但它们都属于Context的一种,而它们具体Context的功能则是由ContextImpl类去实现的,因此在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的。不过有几种场景比较特殊,比如启动Activity,还有弹出Dialog。出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则将会出错。getApplicationContext()和getApplication()方法得到的对象都是同一个application对象,只是对象的类型不一样。Context数量 = Activity数量 + Service数量 + 1 (1为Application)



04

Android线程间通信有几种方式 


  1. Handler机制

  2. runOnUiThread(Runnable action)

  3. View.post(Runnable action)

  4. AsyncTask

  5. 广播

  6. 使用EventBus、RxJava等框架




05

谈谈数组与链表的区别 


  1. 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。


  2. 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。


06

结束语 


如果你有好的答案可以提交至:

https://github.com/codeegginterviewgroup/CodeEggDailyInterview



往期文章:



今日问题:

大家周末愉快不?





快来码仔社群解锁新姿势吧!社群升级:Max你的学习效率


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存