记3月26日顺丰同城科技面试试题

岗位:软件开发岗位

初面,远程视频

以下为个别问题,我进行详细记录,以便后续参考:

  1. 解释:cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。
  2. libcurl主要功能就是用不同的协议连接和沟通不同的服务器~也就是相当封装了的sockPHP 支持libcurl(允许你用不同的协议连接和沟通不同的服务器)。, libcurl当前支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传(当然你也可以使用PHP的ftp扩展), HTTP基本表单上传,代理,cookies,和用户认证
  3. 它支持的通信协议:FTPFTPSHTTPHTTPSTFTPSFTPGopherSCPTelnet、DICT、FILELDAP、LDAPS、IMAPPOP3SMTPRTSP。----curl还支持SSL认证、HTTP POST、HTTP PUT、FTP上传, HTTP form based upload、proxies、HTTP/2、cookies、用户名+密码认证(Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos)、file transfer resume、proxy tunneling。
  4. 以下介绍两种方法以及使用curl获取它们的命令:

         4.1、在表单中,使用get()方法,提交数据:

                   代码:

<form method="GET" action="junk.cgi">
<input type=text name="birthyear">
<input type=submit name=press value="OK">
</form>

那么浏览器上会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单就用GET方法向服务器提交文本框的数据。

例如原始页面是在 www.hotmail. com/when/birth.html看到的,然后您在文本框中输入1905,然后按OK按钮,那么浏览器的URL现在应该是:“www.hotmail. com/when/junk.cgi?birthyear=1905&press=OK”

对于这种网页,curl可以直接处理,例如想获取上面的网页,只要输入:

curl "www.hotmail. com/when/junk.cgi?birthyear=1905&press=OK"

就可以了~

         4.2、使用POST方法用来提交表单信息,POST方法和GET方法的区别在于GET方法使用的时候,浏览器中会产生目标URL,而POST不会。类似GET,这里有一个网页:

<form method="POST" action="junk.cgi">
<input type=text name="birthyear">
<input type=submit name=press value="OK">
</form>

浏览器上也会出现一个文本框和一个标为“OK”的按钮。按下这个按钮,表单用POST方法向服务器提交数据。

这时的URL是看不到的,因此需要使用特殊的方法来抓取这个页面,使用curl来执行这一操作,其命令如下:

curl -d "birthyear=1905&press=OK" www.hotmail. com/when/junk.cgi
  • 给定一个数,如何快速判断这个数是否为2的x次方所对应的数?

  1. 先说一下我的思路:当时一片茫然,首先想到的是用除法来做,可是除法一般都是基于整数来做的,例如5/2得到的结果就是2,而4/2的结果也是2,行不通,我进而转向取余来做,长时间没有碰这些东西,取余一时间也认为不可以。后来我想到了java强大的封装功能,虽然没有实际用到过java中的数学函数,但是我想应该是会有基于对数运算的函数。接下来思考完毕,我将第一个解决方法:使用java封装好的函数进行运算,给面试官说了;显然他不满意;
  2. 后来我又说一个笨方法。首先想到了除法,但是想到了除法的缺陷,我就转向取余,后来和面试官沟通之后,取余是可以的,显然还要高效一点;
  3. 可能面试官已经不想再说这个问题了,但是当时我也想知道是什么高效的方法,面试官给我提示说2是一个特殊的数字,最后他给我说使用进制转换,例如说二进制。我顺着他的思路,想了一下,2的二进制是10,4的二进制是100,8的二进制是1000,那么2^n的二进制应该是1后面n个0。说到这里,我就想是不是将两个数转换为二进制,再进行对比呢?我给面试官说了以这个想法,他说那需要一个一个对比吗?这下我有迷茫了,见我又开始埋头思考,他最后终于说要使用与或运算,就这样,第一个压轴题结束了。
  • 先顺便复习一下对数函数的性质:

参考:https://blog.csdn.net/f1024042400/article/details/52064652 

性质:

1、a^(log(a)(b))=b 
2、log(a)(a^b)=b
3、log(a)(MN)=log(a)(M)+log(a)(N); 
4、log(a)(M÷N)=log(a)(M)-log(a)(N); 
5、log(a)(M^n)=nlog(a)(M) 
6、利用换底公式:log(x)(y) =log(e)(x) / log(e)(y),我们可以这样做:Math.log(1000*10000) / Math.log(2);

解法一:使用java中数学函数对数的方法解决这个问题的代码:

有一点需要注意:这个函数的返回值为double类型,我是强制转换为int类型的;

/**
 * @author 橙橙橙。
 * Date:2019年03月28日
 * 描述:利用Math封装的函数,求出对数的值
 */
public class AboutLog {
	
	public static void main(String[] args) {
		int value = 32;
		int base = 2;
		int res = logFunction(value, base);
		System.out.println(res);
	}

	//写一个函数,利用换底公式进行计算。换底公式:log(x)(y) =log(e)(x)/log(e)(y)
	public static int  logFunction(int value, int base) {
		return (int) (Math.log(value)/Math.log(base));
	}
}

结果如下:

5

解法二:今天看到了博客园上有一个写法,我觉得很好,链接为:https://www.cnblogs.com/daisy0707/p/5279078.html使用位运算进行,看了几遍之后,我也自己写了一下;

在写之前,先复习一下移位是怎么回事?

来自百度百科的说法:移位运算符在程序设计中,是位操作运算符的一种。移位运算符可以在二进制的基础上对数字进行平移。按照平移的方向和填充数字的规则分为三种:<<(左移)、>>(带符号右移)和>>>(无符号右移)。

更加通俗易懂的说法可以理解为:左移就是给一个数乘2,右移就是给一个数除2;所以,对于任意一个数,我们都可以使用移位的方法来运算出它是否为2的n次方的数;代码如下:

/**
 * @author 橙橙橙。
 * Date:2019年3月28日
 * 描述:使用位运算,实现快速判断某个数是否为2^n所对应的数之一
 */
public class TransBin {

	public static void main(String[] args) {

		boolean b1 =  removeShift(4);
		boolean b2 =  removeShift(6);
		System.out.println("4是否为2的n次方所对应的数: " + b1 + "\n6是否为2的n次方所对应的数:  " + b2);
	}

	public static boolean removeShift(int n) {
		//这个判断主要是为了程序的健壮性;
		if(n < 1)
			return false;
		//当n是大于1的整数时,定义一个基数为1
		int count = 1;		
		while(count <= n){  //当我们要检验的这个数小于等于1时,进入循环
			
			if(count == n)  //如果两者 相等,则直接返回true
				return true;
			
			if(count < n)  //如果检验的数较大时,对我们对应的基准数进行左移一位操作。也就是乘2操作
				count <<= 1;
			
			System.out.println(count);
		}
		return false;   //如果到了这里还没返回的话,就是false了,例如n=5时
	}
}

结果:

2
4
2
4
8
4是否为2的n次方所对应的数: true
6是否为2的n次方所对应的数:  false

解法三:根据2与2的n次方所对应的数的特征,使用“与”运算。 2对于的二进制为10,4对应的为100,8对应的为1000……以此类推,2的n次方,对应1后面是n个0,但是当1000 - 1之后,就是0111,1000与0111按位相与,得到的就是0,因此,最简单的方法就是放这个数与它前一位进行相与运算,即可立即算出这个数是否为2的n次方所对应的数!参考:https://www.cnblogs.com/daisy0707/p/5279078.html

代码:

/**
 * @author 橙橙橙。
 * Date:2019年3月28日
 * 描述:使用二进制的特殊性,快速判断一个数是否为2的n次方所对应的数
 */
public class BestMethod {

	public static void main(String[] args) {

		boolean b1 = SimpePanDuan(1024);
		System.out.println("刚才输入的数是否为2的n次方所对应的数? " + b1);
	}

	public static boolean SimpePanDuan(int n) {
		if(n < 1)
			return false;
		
		if((n&(n - 1)) == 0)
			return true;
		
		return false;
	}
}

结果为:

刚才输入的数是否为2的n次方所对应的数? true
  • 描述一个url从执行到获取数据的过程:

  1. 参考:https://blog.csdn.net/xingxingba123/article/details/52743335
  2. 参考:https://blog.csdn.net/weixin_38150378/article/details/79443584
  3. 参考:https://blog.csdn.net/wlk2064819994/article/details/79756669
  • 一个未知长度的单链表,寻找它的中间元素的值,注意时间复杂度

  1. ​​​​​​​首先可以根据Java语言的特点创建一个链表的节点,定义两个属性,一个value,一个节点类型的next;如下所示:
    public class LinkedNode {
    
    	int value;
    	LinkedNode next;
    	
    	public LinkedNode(int value) {
    		this.value = value;
     	}
    }
  2. 写一个函数,传入一个参数值,如果参数值只有一个或者为空,则直接返回。如果有值,则定义两个指针,一个指向当前节点,一个指向当前节点的两倍的节点;这样做主要是当快的指针指向末尾的时候,慢指针正好在中间位置,这时候就可以得到我们想要的值了。如下:
    	public static LinkedNode findMidPoint(LinkedNode head) {
    		if(head == null || head.next == null) {
    			return head;
    		}
    		
    		LinkedNode fastPoint = head;  //定义一个快指针,初始位置在头结点
    		LinkedNode slowPoint = head;  //定义一个慢指针,初始位置在头节点
    		
    		while(fastPoint.next != null) {   //如果当前指针的下一个指针不为空
    			if(fastPoint.next.next != null) {    //如果当前指针的下下位指针不为空
    				slowPoint = slowPoint.next;    //如果满足条件,则慢的指针指向下一个节点;
    				fastPoint = fastPoint.next.next;  //快指针指向下一个节点的下一个节点
    			} else {
    				slowPoint = slowPoint.next;   //如果不满足条件,则指向慢指针的下一个节点
    				return slowPoint;     //此时可以ruturn了
    			}
    		}
    		 return slowPoint;
    	}

    其实fastPoint的指向速度是slowPoint速度的二倍?二倍如何体现?方slow的指向为1时,fast为2;当slow为2时,fast指针为4,每次的增加都是在前一次的基础上,而不是fast在slow的基础上添加的。

  3. 整体实现如下代码:

    /**
     * @author 橙橙橙。
     * Date:2019年3月31日
     * 描述:一个长度未知链表,找出中间节点的值,注意时间复杂度
     */
    public class LinkedNode {
    	int value;
    	LinkedNode next;
    	
    	public LinkedNode(int value) {
    		this.value = value;
     	}
    
    	public static void main(String[] args) {
    		LinkedNode lick1 = new LinkedNode(3);
    		LinkedNode node2 = new LinkedNode(5);
    		LinkedNode node3 = new LinkedNode(6);
    		LinkedNode node4 = new LinkedNode(8);
    		LinkedNode node5 = new LinkedNode(10);
    		LinkedNode node6 = new LinkedNode(19);
    		LinkedNode node7 = new LinkedNode(20);
    		LinkedNode node8 = new LinkedNode(30);
    		
    		//将LinkedNode类的对象连接成一个链表
    		lick1.next = node2;
    		node2.next = node3;
    		node3.next = node4;
    		node4.next = node5;
    		node5.next = node6;
    		node6.next = node7;
    		node7.next = node8;
    		
    		LinkedNode node = findMidPoint(lick1);
    		System.out.println(node.value);
    
    	}
    	
    	public static LinkedNode findMidPoint(LinkedNode head) {
    		if(head == null || head.next == null) {
    			return head;
    		}
    		
    		LinkedNode fastPoint = head;
    		LinkedNode slowPoint = head;
    		
    		while(fastPoint.next != null) {
    			if(fastPoint.next.next != null) {
    				slowPoint = slowPoint.next;
    				fastPoint = fastPoint.next.next;
    			} else {
    				slowPoint = slowPoint.next;
    				return slowPoint;
    			}
    		}
    		 return slowPoint;
    	}
    }
    	

    结果如下:

    10
    

     加油加油!算法开始入门了~耶

     

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值