杂项
介绍下自己 时间一分半以内
提炼自身优点,
优势、亮点、基本情况 言简意赅、语言精炼,控制时间 和应聘岗位相关的经历(和招聘要求相关) 为什么能够胜任岗位 为什么要应聘该岗位~求职动机
不能只介绍学校和专业,
注意:重点介绍满足岗位要求的三个优势和亮点。 表现出对岗位的理解和自己清晰的职业规划。 表示愿意长期从事这个岗位。
示范:
面试官,下午好,我叫,来自、、、、、学院,。 这一次呢,我应聘的是网络研发的工作。从事网络相关的工作呢? 是我一直的梦想。为此呢?在研究生阶段呢? 我很早就结合岗位的要求进行了准备包,包括对各种协议的熟悉,常用算法的实践等,在两年的时间里面呢? 我也重点选择了网络相关的课题,进行了研究,希望能够加入公司从事网络相关的这个工作。 谢谢。
领导您好,我叫,来自、、、、、学院,我面试的岗位是上位机开发,从事软件开发相关的工作是我一直以来的愿望,为此从大学开始就关注行业技术风向,我也是重点选择了.net 相关的技术栈进行学习,包括C# ,wpf,webapi,进行了重点研究。在之前的工作经历中,我也学到了关于软件开发的模式MVVM,和串口之类的协议。当时是通过wpf开发的程序与嵌入式设备进行通信。希望能够加入贵公司从事软件开发这个工作。
你觉得你有什么缺点 / 优点
优点:
注重时间管理,善于归纳总结,做事有条理:期末考试时朋友们总是喜欢借我的笔记复习。做一件事情,我会反推这件事情需要怎么做,一步步反推到当前的时间节点,从而明确应该怎么做,每个阶段应该达成怎样的目标。
我的求知欲比较强,有好奇心,从小就喜欢把东西拆开看个究竟,但是能不能装回去就是个未知数了,为此没少挨揍。现在到大学里也特别喜欢钻研技术,对我来说,钻研技术既是学习也是乐趣。
行动力强,我是一个做事全力以赴的人,或者说是一个比较拼命的人,一旦确定了一个目标,就会用上自己的全部力量,直到成功。为了尽早调通程序,可以一晚上不睡觉靠红牛撑着。备考四级时,由于课业压力大,却还是每天坚持听力,刷单词,做真题,最后高分通过。为了今天和您们这场面试,从接到面试通知那天就开始准备做功课。
缺点:
我的公开演讲能力有些差,但不至于差到话都说不明白的地步, 在公共场合讲话的时候我会感到紧张, 不过谈论我熟悉的领域我会比较放松。所以当我需要做公开发言的时候,我必须要准备得很充分。
我对工业控制和plc领域还不是很了解,尽管做了功课,但是纸上得来终觉浅,和实际的开发需求还是有差距,不过C#编码部分都是相通的,重要的是业务逻辑的学习,我相信自己能快速上手。
不太好意思拒绝别人的求助,有时自己的工作还没有完成,别人来求助,看见别人需要帮忙的情景,我总是不太好意思拒绝
有无读研动机?
暂时没有考研的打算,我觉得实践中能学到的知识,比花三年时间读研究生来的实际,而且我已经是成年人了,我希望自己养活自己。如果以后工作和成长有需要,也许我会再去读个MBA什么的,但是现在我想先实践一下大学期间学到的知识。
过往项目?/ 学到了什么?/ 发挥怎么的作用?
谈谈你对这个职位的理解
.net 工程师。。通过招聘软件上的职位描述,我觉得这个岗位是需要和同事合作开发WPF客户端软件,从对WebAPI和CS架构的要求来看,这个岗位还需要开发一些后端接口供客户端调用。从对数据库设计的要求来看,客户端需要将采集的数据,日志通过数据库持久化存储,以便后续故障分析,软件维护用。现代软件项目开发,很少有一个人完成整个项目的开发,所以应该是团队协作完成,比如有经验的工程师完成接口的规范,整个软件架构的规划,根据项目需求选择合适技术。经验少一点的工程师完成接口的实现与Model模型的编写,并在工作过程中不断学习软件的架构。
熟悉工控软件?时序数据,高并发处理?
时序数据,采集的数据按照时间排序,通过图表显示
PLC,DCS,SCADA,工业控制行业了解?
PLC:可编程逻辑控制器,有着丰富外设的单片机,广泛应用于工业自动化的电子设备,可靠性,灵活性,模块化,易于编程。常见的有西门子,三菱,欧姆龙,施耐德,松下
DCS:分布式控制系统,将控制功能分散到多个分布式的控制单元中,每个控制单元负责控制过程的一个部分,这些控制单元通过网络连接/总线连接,可以相互通信并共享数据,从而实现对整个生产过程中的协调和控制。特点包括:分布式(采用分散式架构,将控制功能分在独立的控制器或节点上,每个节点负责控制特定的过程和设备)可靠性(由于控制功能分散,单个节点的故障不会影响整个系统的运行,因此具有很高的可靠性)灵活性(可以根据生产过程的需要灵活添加或一处节点,是的系统具有很好的灵活性和可拓展性)模块化设计,实时性,高效性,人机界面,高级控制策略。。
SCADA:上位机,supervisory control and data acquistion ,是工业控制系统中的一个关键组成部分,指用于监控和控制工业过程中的计算机系统或软件,通过收集来及下位机(PLC)的数据,对工业过程进行监控,分析和管理。
上位机相当于工业自动化中的大脑,PLC相当于控制感知神经,传感器相当于感知细胞,执行器相当于肌肉
数据采集:通过从PLC,远程控制单元,分布式控制系统收集数据
实时监控:提供数据显示,包括图表,趋势图,仪表盘等形式,以便操作人员可以实时监控生产过程的状态
报警通知:当生产过程中的参数超出预期的安全范围时,上位机会触发报警,并通过声光设备通知操作人员。
过程控制:上位机基于PLC,提供更高层次的指令,如调度生产流程,设置参数,启动或停止设备。
历史数据记录:将生产过程中采集到的数据,日志,记录,设备状态,记录下来,以便故障诊断,性能分析用。
人机界面:提供有好的界面,操作人员可以通过界面与控制系统交互,输入指令或获取信息。
对我们公司的了解有多少?
盾构机,上位机,地下空间工程设备。
专利与盾构机技术相关。机械工程相关专利,科班出身。计算机可以为其赋能增效,做好后勤软件保障。
大学期间有没有基于兴趣做一些技术上的研究?
编,diy键盘,无刷电机控制FOC,模拟旋钮手感,棘轮,阻尼。
IOT气象站,esp8266,风速,温度,湿度,数据上传新大陆云平台,安卓获取
如果给我一个需求,我会如何着手去实现(如何搜索需求的技术,如何解决技术难点)。
明确需求,使用搜索引擎,查阅类似解决方案,寻找可以借鉴的技术点,提出解决方案。向行业前辈讨教思路,寻找有无现成技术可以解决
分解问题:将复杂的问题分解为若干小问题,逐一攻克,团队协作讨论,集思广益,开发环境实践,根据实现的结果进一步优化方案。
反问阶段
公司技术栈
面试什么时候出结果
五险一金怎么交的
试用期多久
复试可能会深挖项目
实习期和转正期,
确定发offer再谈薪资
薪资结构-十几薪-
首先问薪资结构,涨薪范围,
我想先了解贵司的薪酬结构、福利待遇和转正制度(关注点可以从以下几点中选择:薪酬里是否有绩效部分?薪酬里是否包含补贴?实习到期后一定签劳动合同吗?签订劳动合同后试用期是几个月?试用期薪酬打折吗?包吃包住吗?
我看了公司的岗位薪资是10k~15k,而我的自身能力和岗位的匹配度很高,我希望达到公司的要求转正后能拿到12k,试用期拿80%左右,也是岗位薪资范围的最低值。
面试时谈的项目:
简历上两个,建议在自己的项目经历里写上自己拿手的关键词引导面试官去问
着重准备面试要求上的关键词,详细准备,MVVM,MVC,ORM框架
C#
什么是面向对象编程?
以对象作为代码的基本构件,通过对象的交互构建程序,对象是数据和与之关联的方法的集合,对象是现实中实体的抽象,主要特点包括:封装继承多态,
using语法的作用
1.引用类库项目
2.实现了IDisposible接口的类在using中创建,using结束后会自动调用Dispose方法释放资源。
解释封装继承多态,以及在C#中的作用
封装:对象的数据和行为被封装在一起,使得对象内部状态只能由定义好的接口进行访问和修改,提高了数据的安全性。
继承:允许新的对象类继承现有的对象类的属性和方法,促进了代码的复用。
多态:一个接口可以有不同的实现
CLS,CTS,CLR?
CLS:Common Language System 通用语言系统
CTS:Common Type System 通用类型系统
CLR:Common Language Runtime 公共语言运行时 编译成IL(中间语言),可以在CLR上执行
C#中 private、 protected、 public、 internal 修饰符的访问权限
private:私有成员,只有在类的内部才可以访问
protected:保护成员,该类内部和继承类中可以访问
internal:公共成员,在同一命名空间内可以访问
public :完全公开,没有访问限制
C#中有哪几种数据类型?分别都有哪些?区别有哪些?
值类型,直接包含数据,在栈上为变量分配内存,直接存储实际数值
int byte bool short long uint float 结构体
引用类型,引用类型存储对内存中对象的引用,而不是存储实际数据,引用类型在堆上,被引用的对象在栈上,
类,接口,数组,委托,字符串。
REF OUT什么区别,作用
都是用来传递变量的关键字,ref按引用传递参数,out也用于按引用传递参数,传递出去。
ref需要初始化,out不需要
重写重载的区别
重写⽅法:关键字⽤override修饰,派⽣类重写基类的⽅法,⽅法命名、返回类型,参数必须相同 重载⽅法:⽅法名必须相同,参数列表必须不相同,返回类型可以不相同。 作⽤:重写主要是实现⾯向对象的多态性、重载主要是实现实例化不同的对象
当⼀个类需要⽤不同的实现来做同⼀件事情,此时应该⽤重写,⽽重载是⽤不同的输⼊做同⼀件事情
String、StringBuffer、StringBuilder之间区别
1.三者在执行速度方面的比较: StringBuilder >StringBuffer > String
String一旦赋值或实例化后就不可更改(String被final修饰,所以不可变),如果赋予新值将会重新开辟内存地址进行存储。而StringBuffer类使用append和insert等方法改变字符串值时只是在原有对象存储的内存地址上进行连续操作,减少了资源的开销。因此:当需要进行频繁修改字符串的操作时先建立StringBuffer类对象进行操作,将最后结果转化成String类对象返回,这样效率会高很多。
StringBuffer(StringBuilder)其实可以看做“基本数据类型”String的包装类(Wrapper),就像int与之对应的Integer等关系。StringBuffer有缓存的,如果你声明一个字符串只是接收传过来的参数,然后进行业务逻辑处理,那么假如你用很多个StringBuffer类型的对象,就比较浪费内存。这样用String就更好。
-
在字符串拼接时,String 对象的速度并不会比 StringBuffer对象慢。
String 对象的字符串拼接其实是被 JVM 解释成了StringBuffer 对象的拼接,所以这些时候String 对象的速度并不会比StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快。
集合 IList 接⼝与List的区别是什么?
IList 泛型接⼝是 Icollection 接⼝的⼦代,并且是所有⾮泛型列表的基接⼝。 Ilist 实现有三种类别:只 读、固定⼤⼩、可变⼤⼩。 ⽆法修改只读 Ilist。 固定⼤⼩的 Ilist 不允许添加或移除元素,但允许修改 现有元素。 可变⼤⼩的 Ilist 允许添加、移除和修改元素。 IList 是个接⼝,定义了⼀些操作⽅法这些⽅法要你⾃⼰去实现,当你只想使⽤接⼝的⽅法时,这种⽅式⽐ 较好.他不获取实现这个接⼝的类的其他⽅法和字段,有效的节省空间. List 是个类型 已经实现了IList 定义的那些⽅法。
能用ForEach遍历的对象的要求?:需要实现IEnumerable接口或声明GetEnumerator方法。
说出5个集合类:List Dictionary HashMap SortedList Stack
异常
C#中,所有异常都继承⾃System.Exception类。
可以使用Try catch捕获异常,可以通过捕获不同类型的异常执行不同的操作,最后执行finally代码块里内容释放资源
泛型 - 主要约束,次要约束?
主要约束可以是⼀个引⽤类型、class或者struct。如果指定⼀个引⽤类型(class),那么实参必须是该类型或者该类型的派⽣类型。相反,struct则规定了实参必须是⼀个值类型
次要约束主要是指实参实现的接⼝的限定。对于⼀个泛型,可以有0到⽆限的次要约束,次要约束规定 了实参必须实现所有的次要约束中规定的接⼝
优点:代码的可重⽤性。⽆需从基类型继承,⽆需重写成员。 扩展性好。 类型安全性提⾼。 泛型将类型安全的负担从你那⾥转移到编译器。 没有必要编写代码来测试正确的数 据类型,因为它会在编译时强制执⾏。 降低了强制类型转换的必要性和运⾏时错误的可能性。 性能提⾼。泛型集合类型通常能更好地存储和操作值类型,因为⽆需对值类型进⾏装箱。
委托
委托是一种类型,声明委托就是声明一个类型(传入参数,返回参数)
委托是寻址的.NET版本(升级版),定义了返回类型和参数列表。
像做代码填空题一样能当作参数传入方法体内,执行不同的功能
public delegate void Feedback(int num);
默认委托类型有:Action --void返回值,至多16个参数
Func --带返回类型方法,带参数
泛型委托指不关注参数和返回值的类型,Action<T>,提高代码灵活性,只需要关注泛型的参数列表和返回值的个数。
拓展方法
使用This关键字,拓展类的方法,
例如拓展Double类的方法
可以写一个为DoubleExtension的类,里面写要加入的方法,
静态类中的静态方法,第一个关键字用this修饰
介绍 LAMBDA LINQ
LAMBDA表达式是一种匿名函数,可以在声明委托时用lambda表达式实例化
LINQ:语言集成查询
LINQ可视化工具linqpad,查询lambda表达式,编译的sql
LINQ2OBJ,数据源是类型提供的实现IEnumerable,
LINQ2SQL是实现Quaryable的拓展方法
有50万个int类型的数字,现在需要判断⼀下⾥⾯是否存在重复的数字,请你简要说⼀下思路
使⽤C#的List集合⾃带的去重⽅法,例如 Distinct(),GroupBy()等
利⽤ Dictionary 的Key值唯⼀的特性,HashSet 元素值唯⼀的特性 进⾏判断
EFCORE--ORM框架
以面向对象的思想来做数据库查询
ORM框架:EFCORE-sqlsurgar-dapper-IBATIS
sqlsurgar是国产开源的orm框架,其宣传大数据量插入效率远高于其他框架
较ado.net提高开发效率
ORM:实体关系映射,
sqlsurgar:db.getLastSQL获取最后执行的sql
三种模式
Database First(先有数据库)
CodeFirst(现有代码)
混合模式
跟踪查询,连接查询
委托和事件
1、委托:将方法以变量的形式传递,并且以方法的形式执行。他是类,是引用类型。
2、事件:功能被限制的一个委托变量。它的类型是委托类型。
3、委托的三种形式
3.1、delegate: 四步(声明,实例化,注册方法,调用)
3.2、Action:添加的方法不能有返回值
3.3、Func: 添加的方法要有返回值
3.4、lamda表达式:方法只使用一次,没有多次使用的话使用
1.事件的声明只是在委托前面加一个event关键词,虽然你可以定义一个public,但是有了event关键词后编译器始终会把这个委托声明为private,然后添加1组add,remove方法。add对应+=,remove对应-=。这样就导致事件只能用+=,-=来绑定方法或者取消绑定方法。而委托可以用=来赋值,当然委托也是可以用+=,-=来绑定方法的。
2.委托可以在外部被其他对象调用,而且可以有返回值(返回最后一个注册方法的返回值)。而事件不可以在外部调用,只能在声明事件的类内部被调用。我们可以使用这个特性来实现观察者模式。大概就是这么多
-
声明事件:首先,在类的声明中声明一个事件。例如:
public class MyClass
{
public event Action<string> MyEvent;
} -
订阅事件:一个类可以订阅另一个类声明的事件。订阅者提供事件处理方法的引用。
MyClass myClass = new MyClass();
myClass.MyEvent += HandleEvent; -
发布事件:当发布者想要触发事件时,它调用事件的名字并传递任何必要的参数。
myClass.MyEvent?.Invoke("事件内容");
-
事件处理方法:在订阅者中,有一个方法与事件相关联,这个方法会在事件被触发时执行。
private void HandleEvent(string message)
{
Console.WriteLine($"事件被触发,内容是:{message}");
}
控制反转
(Inversion of Control,缩写为IoC),是⾯向对象编程中的⼀种设计原则,可以⽤来减低计 算机代码之间的耦合度。其中最常⻅的⽅式叫做依赖注⼊(Dependency Injection,简称DI),还有⼀ 种⽅式叫“依赖查找”(Dependency Lookup)。 通过控制反转,对象在被创建的时候,由⼀个调控系统内所有对象的外界实体将其所依赖的对象的引⽤ 传递给它。也可以说,依赖被注⼊到对象中。
多线程-背后的机制(Thread-Task)
可以发挥多核cpu的优势,防止UI线程阻塞,出现卡顿。
多线程背后的机制主要包括线程的创建、线程的状态管理、线程的同步和通信以及线程的调度等。
-
线程的创建:通过继承Thread类或实现Runnable接口来创建线程。当调用线程的start()方法时,系统会为该线程创建PCB(进程控制块)并将其加入链表,之后系统在调度时会执行run()方法10。
-
线程的状态管理:线程在其生命周期中会经历若干个状态,如新建(NEW)、就绪(RUNNABLE)、运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)等。这些状态可以通过线程的状态方法进行获取和切换5。
-
线程的同步:线程同步主要是通过互斥锁、synchronized关键字、读写锁、条件变量以及事件等机制来确保多线程访问共享资源时的互斥性和有序性65。
-
线程的通信和调度:线程间的通信主要是通过等待唤醒机制、局部变量、阻塞队列等方式实现的3。线程的调度则依赖于操作系统的调度算法,如抢占式调度和协作式调度等2。
综上,多线程编程涉及许多复杂的概念和机制,但其核心在于正确地管理线程的创建、状态、同步和通信,以实现多线程的高效和有序运行。
锁-死锁
锁 是一种同步机制(锁的本质是monitor),用于防止多个线程同时访问资源,当一个线程访问资源时,它可以对对象加锁,以防止其他线程访问该对象,直到当前线程释放锁,其他线程才能访问该对象,在C#中,锁使用lock关键字实现,锁对象必须是引用类型。如果是值类型,每次会进行装箱操作,每次装箱后的对象不一样,会导致锁无效。
class Program
{
private static object _lockObject = new object();
static void Main()
{
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(() => PerformOperation());
t.Start();
}
}
static void PerformOperation()
{
lock (_lockObject)
{
// 这段代码是临界的,只有一个线程可以执行
Console.WriteLine("Thread {0} is executing critical code.", Thread.CurrentThread.ManagedThreadId);
}
}
}
//注意这段代码不会造成死锁,因为int是值传递,如果换成引用类型会造成死锁。
public void test(int i)
lock(this)
{
if (i>10)
{
i--;
test(i);
}
}
线程和进程的区别一个进程可以包含多个线程,进程相当于家庭,线程相当于家庭成员,共享资源。进程能访问的最大内存为,2^(处理器位数-1)
引入线程池来管理线程的创建与销毁可以节省资源,可以通过ThreadPool类型提供的静态方法来获取当前可用的线程数量,以及最大线程数。
ThreadPool.SetMaxThreads(100,100);
线程池可以减小线程创建销毁的开销,可以复用线程,减少了线程上下文切换造成的损失,无法对一个线程有更多精细的控制,如了解其状态,不能设置线程的优先级,不能有返回值。start(开始),abort(终止),join(等待执行结束),yield(歇一会)ThreadState线程状态,CurrentThread当前线程。
客户端与设备通讯机制(上位机)
客户端与设备通讯机制(上位机)通常涉及到硬件通信和数据交换。上位机通常指的是计算机系统,它通过一定的通信协议和接口与各种设备进行数据交互。
-
串行通信:通过串行端口(如COM端口)进行数据传输。这种通信方式速度较慢,但适用于远距离通信和简单的数据交换。
-
并行通信:通过并行端口进行数据传输,这种方式速度较快,但适用于短距离通信。
-
USB通信:USB接口已成为现代计算机与外部设备通信的通用接口,支持高速数据传输,适用范围广泛。
-
网络通信:通过以太网、Wi-Fi或蓝牙等网络技术进行数据传输。这种方式可以实现较远距离的高速数据交换,适用于现代的智能设备和服务器之间的通信。
-
无线通信:包括Wi-Fi、蓝牙、NFC、RFID等无线技术,这些技术使得设备之间的通信更加灵活,不受物理连接的限制。
-
总线通信:在嵌入式系统中,设备可能通过总线(如I2C、SPI、CAN等)进行通信。这些总线协议通常用于连接微控制器与各种传感器、存储器、显示器等外设。
-
无线模块:如GSM、CDMA、4G/5G等无线通信模块,可以实现设备通过移动网络进行数据传输。
在实现客户端与设备的通信时,通常需要考虑以下几个方面:
-
协议转换:不同设备可能支持不同的通信协议,上位机需要能够转换和适配这些协议。
-
数据格式:确保上位机和设备之间传输的数据格式是一致的,以便于正确解析和处理。
-
错误处理:在通信过程中可能会出现错误,上位机需要有相应的错误检测和处理机制。
-
数据安全:对于敏感数据,需要加密传输以保证数据的安全性。
-
实时性:对于实时性要求较高的应用,通信机制需要能够保证数据的及时传输
async,await,task
都能通过创建多线程的方法执行,task较新,可以使用async await,还能使用线程池(默认)
使用async声明异步方法,await关键字用于等待一个异步操作的完成。
通过使用async,await可以避免回调函数的使用。
.NET体系架构
托管代码
托管是什么意思,说白了就是让CLR管理着应用程序,从源代码到MSIL,再到本机代码,再到程序执行,由.NET与操作系统进行交互。不在CLR控制之下运行的应用程序时非托管的。
托管代码最重要的一个功能是无用存储单元收集(garbage collection),也称垃圾回收,确保应用程序不再使用某些内存时,这些内存会被完全释放。
.NET常用库
Prism 实现MVVM设计模式
Log4Net 实现日志,文本/数据库
Dapper ORM框架,SQLSurgar框架
autoMapper obj-obj映射库,解决模型之间转换映射 dto-model
NModbus4 与Modbus TCP通讯
LiveCharts 图表库
SerialPort 应用于串口通讯
moq 常用于单元测试,生成假数据
解释C#和.NET之间的关系
C#是一门编程语言,.NET是微软推出的一个框架,在基础设施之上,再往上有.NET standard library(基础类库),再往上就是各种领域的框架,比如桌面端有WPF,移动端有MAUI,服务端有asp.net,游戏领域有Unity
ADO.NET
1.Connection对象
Connection 对象就像是打仗时候的通信兵,他们在打仗之前需要先接通司令部与各个作战单位之间的通信线路。之后作战命令的获取以及发布都要靠通信线路来完成。这里的司令部就类似于服务器,各作战单位就类似于各应用程序。
2.Command对象
执行一些简单操作命令,如:增删改删,即执行T-SQL语句。Command对象有几个比较重要的方法,如ExecuteNonQuery()方法,执行增删改命令,返回的是受影响的行数。查询方法有2种:一个是ExecuteReader()方法,返回一个DataReader对象。还有ExecuteScale()方法,返回首行首列值。
3.DataAdapter对象
数据适配器,从数据库中检索数据,再填充到本地数据集中。同时,我们可以利用DataAdapter,再将数据反向从DataSet中更新回数据库。DataAdapter使用中主要有4个命令对象比较重要。它们分别是:SelectCommand、InsertCommand、UpdateCommand、DeleteCommand。SelectCommand,主要是从数据库中检索数据InsertCommand、UpdateCommand、DeleteCommand这3个命令对象主要负责把本地数据集DataSet中的数据上传回服务器。我们主要使用的是前者。DataAdapter的Fill方法,用于使用DataAdapter的SelectCommand的执行结果集来填充DataSet。
4.DataReader对象
当我们只需要循序的读取数据而不需要其它操作时,可以使用DataReader 对象。DataReader对象只是一次一笔向下循序地读取数据源中的数据,不作其它的操作。因为DataReader 在读取数据的时候限制了每次只读取一笔,而且只能只读,所以使用起来不但节省资源而且效率很好。此外,因为不用把数据全部传回,故可以降低网络的负载。但是,当我们从数据源中一条一条的读取数据的时候,一定记得要时刻打开数据库的连接。
5.DataSet对象
DataSet 这个对象可以视为本地内存中的一个数据库,可以把从数据库中所查询到的数据保留到本地。DataSet 的能力不只是可以储存多个Table,还可以透过DataAdapter 对象取得一些例如主键等数据表结构,并可以记录数据表间的关联。当我们使用DataSet读取数据的时候,数据库的连接是否关闭已经无关紧要了。DataSet 对象可以说是ADO.NET 中重量级的对象,通过DataAdapter 对象这个桥梁,实现了与数据源沟通的能力 。
笔试基础问题!!!
递归题
WPF
什么是依赖项属性
是wpf中的一项技术,是一种特殊的属性,允许属性值依赖于其他属性,比如数据绑定,样式,动画,或其他依赖值
什么是双向绑定
双向绑定是指MVVM模式中,model与view的绑定,
model到view的绑定是通过继承并实现INotifyPropertyChange方法
view到model的绑定是通过绑定数据实现
最后在cs文件中对DataContaxt=new ViewModel();
什么是响应式
允许程序的界面能够根据窗口大小,分辨率等的变化自动调整布局和元素的大小,
可以通过内置的布局面板,如grid,stackpanel,wrappanel dockpanel用来创建响应式布局。
可以通过触发器,视觉状态,实现更复杂的响应式布局。使得可以根据控件的属性来改变控件的样式和行为。
使用相对尺寸,而不是绝对尺寸。
使用布局面板的属性来控制对齐和分布。
什么是样式
WPF中,样式是一种用于定义控件外观和行为的控件,
可以包含触发器,当其被触发时,来设置控件的样式
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<!-- 其他Setter -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style>
为什么选择C# wpf开发
C#的简洁性和易用性,MVVM支持,社区和生态支持
因为C#的官方性极强,有很多官方的学习文档,而且更新及时,可以很快的入门
.net 生态经过近些年的发展优化,.net core 也能跨平台了,而且C#开发的代码编译后执行效率越来越高,越来越安全,.net框架之上的多种应用领域微软都有与之对应的技术栈和框架,能极大程度的提升开发人员的效率。比如桌面开发有WPF,WinUI,移动端开发有MAUI,server端开发有asp.net core,网页应用开发有blazor,这些技术框架只要掌握了C#,其他的特性基本上都大同小异。得益于windows平台的特性使得与硬件通讯如此的简单,而wpf在工控领域更是一直独秀的存在。
XAML
1 XAML是eXtensible Application Markup Language的英⽂缩写,相应于中⽂称为可扩展应⽤程序标记语⾔,它是微软公司为构建应⽤程序⽤户界⾯⽽创建的⼀种新的描述性语⾔。 2 XAML是XML语⾔的⼀个衍⽣物,它的语法与XML语⾔完全⼀致,它的功能就是专⻔⽤来设计和实现程序的UI。 3 XAML⼀个很⼤的优点就是由于WPF⽀持WEB开发,那么WEB开发和桌⾯开发的转换是很简单,修改的地⽅很短,同时UI与逻辑完全分离,所以逻辑代码也⼏乎不⽤改动
自定义控件-回答时可延伸至三方控件库HandyControl
确定控件类型
创建控件类,并继承自Control类
定义依赖属性
处理布局和尺寸
数据绑定
创建样式和模板
测试和优化。
WPF中创建自定义图表控件是一个相对复杂的过程,因为它通常涉及到图形渲染、数据绑定、事件处理和可能的用户交互。因此使用第三方控件库而不是重复造轮子是个不错的选择
C/S架构开发模式
客户端,服务端
客户端通常是一个WPF应用程序,可以发送请求到服务器,也可以接受服务器的响应来更新用户界面
WPF客户端软件开发流程(至打包部署)
需求分析,概要设计,详细设计,编码,测试,debug,打包部署,维护
什么是DDD
domain drive design,强调基于业务领域的复杂性来进行软件设计。
硬把实现重点放在业务逻辑和领域知识上,而不是技术上。
强调领域驱动技术,而不是技术发展驱动领域。
简而言之,做开发最重要的就是做业务
数据库
你了解的数据库优化有哪些?
创建索引,定期维护和创建索引,仅查询必要的字段以减少数据量,使用存储过程,
第一范式,第二范式,第三范式
第一范式:数据表中的字段不可再分
第二范式:数据表中的字段都与主键有关
第三范式:数据表中的字段都与主键直接相关
数据库注入攻击,如何避免
通过拼接字符串的形式,向数据库植入恶意代码以获取权限
通过值传递,明确用于输入的只能作为sql查询的值,
使用ORM框架
优化,索引,存储过程,触发器
-
关系型数据库:
-
关系型数据库是一种使用关系模型来组织数据的数据库,数据以表格的形式存储,表格之间通过关系进行连接。常见的关系型数据库包括 MySQL、Oracle、SQL Server 等。
-
-
SQL(Structured Query Language 结构化查询语言):
-
SQL 是一种用于管理关系型数据库的标准语言,通过 SQL 可以实现对数据库的查询、更新、删除等操作。SQL 分为数据操作语言(DML)、数据定义语言(DDL)、数据控制语言(DCL)等类型。
-
-
表(Table):
-
表是数据库中存储数据的基本单位,类似于电子表格中的工作表。表由行和列组成,每一行表示一个记录,每一列表示一个字段。
-
-
字段(Column):
-
表中的每一列都代表一个字段,字段定义了数据的类型和约束条件,例如整数、字符串、日期等。
-
-
记录(Row):
-
表中的每一行称为一条记录,记录了一组相关的数据。
-
-
主键(Primary Key):
-
主键是表中的唯一标识符,用于唯一标识表中的每一条记录。主键值不能重复且不能为空。
-
-
外键(Foreign Key):
-
外键是一个表中的字段,它与另一个表中的主键字段相关联,用于建立表与表之间的关联关系。
-
-
事务(Transaction):
-
事务是数据库管理系统执行的一个操作序列,它被视为一个单独的工作单元,要么完全执行,要么完全不执行。事务具有 ACID 属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
-
-
索引(Index):
-
索引是一种数据结构,用于加速对表中数据的检索。通过索引,数据库可以快速定位到符合特定条件的记录,从而提高查询性能。
-
CREATE INDEX idx_username ON users (username);
-
-
触发器(Trigger):
-
触发器是一种特殊的存储过程,它会在表发生特定事件(如插入、更新、删除)时自动执行。触发器常用于实现数据约束和业务逻辑。
-
CREATE TRIGGER insert_order_log
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
DECLARE log_msg VARCHAR(255);
SET log_msg = CONCAT('New order (ID: ', NEW.order_id, ') inserted on ', NOW());
INSERT INTO order_logs (order_id, log_message) VALUES (NEW.order_id, log_msg);
END;
//NEW关键字获取插入的数据元素
第一范式:字段不可分
第二范式:每列都与主键相关,(直接相关,间接相关)
第三范式:每列都与主键相关,且不存在间接相关。
-
-
存储过程
存储过程(Stored Procedure)是一种在数据库中预编译和存储的SQL语句集合,它是一种数据库脚本,可以在数据库中执行。存储过程通常包含一系列SQL语句,用于执行数据查询、数据更新、数据插入、数据删除等操作。
存储过程的优点包括:
提高性能:由于存储过程是在数据库中预编译的,因此执行时不需要再次编译,可以减少数据库的负载,提高执行速度。 安全性和权限控制:可以限制用户只能通过存储过程访问数据,从而减少直接执行SQL语句的风险。 可重用性:存储过程可以被多次调用执行,减少了重复编写SQL语句的工作量。 易于维护:当需要修改数据操作逻辑时,只需修改存储过程的代码,而不需要修改调用存储过程的客户端代码。 存储过程通常由CREATE PROCEDURE语句创建,并使用EXECUTE或CALL语句执行。下面是一个简单的存储过程示例,该过程用于查询某个表中的记录数:
sql 复制 -- 创建一个名为 'GetRecordCount' 的存储过程 CREATE PROCEDURE GetRecordCount AS BEGIN -- 设置返回消息 SET NOCOUNT ON;
-- 创建一个名为 'GetRecordCount' 的存储过程
CREATE PROCEDURE GetRecordCount
AS
BEGIN
-- 设置返回消息
SET NOCOUNT ON;
-- 执行SQL查询并返回结果
SELECT COUNT(*) AS RecordCount
FROM YourTableName;END; 使用存储过程时,可以通过参数传递值,也可以返回结果集。下面是一个带有参数和返回结果集的存储过程示例:
sql 复制 -- 创建一个名为 'GetEmployeesByDepartment' 的存储过程 CREATE PROCEDURE GetEmployeesByDepartment @DepartmentID INT AS BEGIN -- 设置返回消息 SET NOCOUNT ON;
-- 执行SQL查询并返回结果
SELECT EmployeeID, EmployeeName, DepartmentID
FROM Employees
WHERE DepartmentID = @DepartmentID;END; 在客户端应用程序中,可以通过执行以下命令来调用存储过程:
sql 复制 -- 调用 'GetRecordCount' 存储过程 EXECUTE GetRecordCount; 或者:
sql 复制 -- 调用 'GetEmployeesByDepartment' 存储过程,传递参数值 EXECUTE GetEmployeesByDepartment @DepartmentID = 1; 存储过程是数据库管理中一个非常重要的功能,可以大大提高数据库的性能和安全性,同时简化代码的维护工作。
MVVM
什么是MVVM?
MVVM是一种设计模式,Model-View ViewModel
MVVM(Model-View-ViewModel)是一种软件设计模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和视图模型(ViewModel)。这种模式主要用于分离用户界面(UI)和业务逻辑,使得应用程序更加模块化、易于维护和测试。MVVM在WPF(Windows Presentation Foundation)、Silverlight、UWP(Universal Windows Platform)和其他支持数据绑定的框架中得到了广泛的应用。
以下是MVVM中各个组件的职责:
-
模型(Model):
-
模型是代表应用程序数据和业务逻辑的部分。
-
它通常包含了数据访问层(如数据库操作)和业务规则。
-
模型是视图模型的数据来源。
-
-
视图(View):
-
视图是用户界面,负责展示数据和与用户交互。
-
它通常由XAML定义,可以包含控件、布局和其他UI元素。
-
视图与视图模型通过数据绑定进行交互,不直接与模型交互。
-
-
视图模型(ViewModel):
-
视图模型是视图和模型之间的桥梁,负责将模型的数据转换为视图可以展示的形式。
-
它包含了视图需要的所有逻辑,如命令(Commands)、事件处理和业务逻辑。
-
视图模型不直接知道视图的存在,它通过数据绑定与视图进行交互。
-
MVVM的关键特性包括:
-
数据绑定:视图模型和视图之间的交互主要通过数据绑定实现。这包括单向绑定、双向绑定和命令绑定。
-
依赖属性:WPF中的依赖属性允许视图模型向视图公开属性,这些属性可以响应用户输入或其他事件。
-
命令:命令在MVVM中用于处理用户操作,如按钮点击。命令通常与视图模型中的方法关联,并可以在视图模型中定义执行逻辑。
-
通知属性变更:视图模型实现了
INotifyPropertyChanged
接口,当属性值发生变化时,它会通知视图进行更新。
MVVM的优势在于它提供了清晰的分离关注点,使得应用程序的不同部分可以独立开发和测试。它也促进了代码的重用和维护,因为UI逻辑和业务逻辑是分离的。
MVVM的本质是什么?
将模型与视图通过viewmodel这座桥连接
实现mvvm的框架用过那些?
MVVMLights
Prism
WebAPI(接口)
什么是WebAPI?谈谈你对WebAPI的理解
WebAPI是一种框架,用于创建HTTP服务,它允许客户端通过HTTP请求访问和操作数据。WebAPI是ASP.NET的一部分,专门用于构建RESTful服务,这些服务可以由各种客户端(如浏览器、移动应用、桌面应用)使用。
以下是关于WebAPI的几个关键点:
-
RESTful原则:WebAPI遵循REST(Representational State Transfer)架构风格,这意味着它使用标准的HTTP方法(如GET、POST、PUT、DELETE)来操作资源。每个方法都有特定的语义,例如GET用于检索数据,POST用于创建数据,PUT用于更新数据,DELETE用于删除数据。
-
跨平台和可扩展性:WebAPI服务的客户端可以是任何能够发送HTTP请求的应用程序,这使得WebAPI非常适合于构建面向服务的架构(SOA)和跨平台应用程序。
-
内容协商:WebAPI支持内容协商,这意味着它可以根据客户端请求的Accept头返回不同格式的数据,如JSON、XML、HTML等。
-
路由:WebAPI使用路由机制将HTTP请求映射到控制器和动作方法。路由规则定义了如何将URL映射到控制器和动作。
-
模型绑定和验证:WebAPI提供了模型绑定功能,它可以将HTTP请求的数据自动映射到.NET对象。同时,WebAPI还支持数据验证,可以在动作方法执行之前验证请求数据的有效性。
-
过滤器:WebAPI允许使用过滤器来拦截请求处理管道,从而实现诸如身份验证、日志记录、异常处理等横切关注点。
-
依赖注入:WebAPI支持依赖注入(DI),这使得它可以更容易地管理和测试应用程序的依赖关系。
-
异步处理:WebAPI支持异步编程模型,允许控制器动作方法以异步方式执行,这有助于提高应用程序的性能和可伸缩性。
-
版本控制:WebAPI支持API版本控制,允许在不中断现有客户端的情况下引入新的API版本。
WebAPI的理解不仅仅是关于它的技术实现,还包括它如何促进良好的API设计原则,如无状态、可缓存、统一接口等。通过WebAPI,开发人员可以创建易于使用、易于维护且功能强大的HTTP服务。
什么是依赖注入?
依赖注入是一种设计模式,用于实现IOC,依赖控制反转,以减少类之间的耦合度。
依赖注入(Dependency Injection,简称DI)是一种设计模式,用于实现控制反转(Inversion of Control,简称IoC)。在WPF中,依赖注入可以帮助开发者创建更加模块化、可测试和可维护的应用程序。依赖注入的核心思想是将组件的依赖关系从组件内部转移到外部,由外部容器负责提供所需的依赖。
以下是依赖注入在WPF中的应用:
-
解耦组件:通过依赖注入,WPF应用程序中的各个组件(如视图模型、服务、仓库等)可以彼此独立开发,减少组件间的直接依赖关系。
-
提高可测试性:依赖注入使得单元测试更加容易,因为可以通过注入模拟对象(mocks)或存根对象(stubs)来隔离测试单个组件。
-
配置和管理依赖:依赖注入容器(如Unity、Ninject、Autofac等)可以用来管理对象的创建和生命周期,以及对象之间的依赖关系。
-
灵活性和可扩展性:当应用程序需要添加新的功能或组件时,依赖注入可以使得这个过程更加灵活和无缝,无需修改现有代码。
-
分离关注点:通过将依赖关系的管理从业务逻辑中分离出来,开发者可以更加专注于业务逻辑的实现,而不是依赖关系的创建和维护。
在WPF中实现依赖注入通常涉及以下步骤:
-
定义接口:为应用程序中的组件定义接口,这样可以减少组件间的直接依赖,便于替换实现。
-
创建依赖注入容器:选择一个依赖注入容器,并在应用程序启动时配置好容器,定义如何创建和解析对象。
-
注入依赖:在需要的地方,通过构造函数注入、属性注入或方法注入等方式,将依赖注入到组件中。
-
使用依赖:组件可以使用注入的依赖进行操作,而无需关心依赖的创建和管理。
依赖注入是一种强大的模式,它可以帮助WPF开发者构建更加灵活和可维护的应用程序。通过合理使用依赖注入,可以提高代码的质量和开发效率。
什么是容器?有哪些容器?
在软件开发中,容器通常指的是依赖注入(Dependency Injection,DI)或控制反转(Inversion of Control,IoC)框架中的核心组件,它负责管理对象的创建和生命周期,以及对象之间的依赖关系。容器负责创建、配置和组装应用程序的组件,使得开发者可以更加专注于业务逻辑的实现,而不是依赖关系的创建和维护。
中间件技术
中间件是组装到应⽤程序管道中以处理请求和响应的软件。 每个组件: 选择是否将请求传递给管道中的下⼀个组件。 可以在调⽤管道中的下⼀个组件之前和之后执⾏⼯作。 请求委托(Request delegates)⽤于构建请求管道,处理每个HTTP请求。 请求委托使⽤Run,Map和Use扩展⽅法进⾏配置。单独的请求委托可以以内联匿名⽅法(称为内联中 间件)指定,或者可以在可重⽤的类中定义它。这些可重⽤的类和内联匿名⽅法是中间件或中间件组 件。请求流程中的每个中间件组件都负责调⽤流⽔线中的下⼀个组件,如果适当,则负责链接短路
什么是 RESTful API?如何在 C# 中创建一个 RESTful 服务?
转述性状态传递。
.net MVC(接口)
什么是MVC架构?谈谈你对MVC的理解
MVC(Model-View-Controller)是一种软件设计模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式主要用于Web应用程序和桌面应用程序的开发,以实现代码的分离和重用,提高应用程序的可维护性和可扩展性。
以下是MVC中各个组件的职责:
-
模型(Model):
-
模型是应用程序的核心,它代表应用程序的数据和业务逻辑。
-
模型可以包含数据访问层(如数据库操作)和业务规则。
-
模型不关心如何显示数据,它只关注数据和业务逻辑。
-
-
视图(View):
-
视图是用户界面,负责展示数据。
-
视图通常由HTML、CSS和JavaScript等标记语言和脚本语言编写。
-
视图不包含任何业务逻辑,它只负责显示数据。
-
-
控制器(Controller):
-
控制器是模型和视图之间的桥梁,负责接收用户输入并处理用户请求。
-
控制器包含业务逻辑,它接收用户的请求,调用模型进行数据处理,并根据处理结果选择适当的视图进行展示。
-
控制器不包含任何UI逻辑,它只包含业务逻辑。
-
MVC的优势在于它提供了清晰的分离关注点,使得应用程序的不同部分可以独立开发和测试。它也促进了代码的重用和维护,因为UI逻辑和业务逻辑是分离的。
为什么用MVC
分离前后端,减少无用代码,提高代码复用性
通讯接口协议
串口,485-232,,MQTT,IOT,IIC,SPI,蓝牙,
TCP,UDP
TCP(传输控制协议)和UDP(用户数据报协议)是TCP/IP协议族中的两个重要协议,它们用于在网络中传输数据。它们的主要区别在于它们如何处理数据传输的可靠性和效率。
TCP(传输控制协议):
-
面向连接:在发送数据之前,TCP需要建立一个连接。这意味着在发送数据之前,发送方和接收方必须先进行握手,以确认双方的通信能力。
-
可靠传输:TCP确保数据的可靠传输,它通过序列号、确认应答、重传机制、流量控制和拥塞控制等机制来保证数据的正确性和完整性。
-
数据包大小限制:TCP的传输单元称为段(segment),其最大大小受到MTU(最大传输单元)的限制。
-
流量控制:TCP使用滑动窗口机制来控制发送方的数据发送速度,以避免接收方处理不过来。
-
拥塞控制:TCP通过慢启动、拥塞避免、快速重传和快速恢复等机制来适应网络拥塞,并调整数据传输速率。
-
广泛应用:TCP是互联网上最常用的协议之一,它适用于需要可靠数据传输的应用,如网页浏览、文件传输、电子邮件等。
UDP(用户数据报协议):
-
无连接:UDP不需要建立连接,可以直接发送数据。
-
不可靠传输:UDP不保证数据的可靠传输,它不进行序列号、确认应答、重传机制等操作。
-
数据包大小限制:UDP的传输单元称为数据报(datagram),其最大大小同样受到MTU的限制。
-
没有流量控制:UDP不进行流量控制,发送方可以以任何速度发送数据。
-
没有拥塞控制:UDP不进行拥塞控制,发送方不会根据网络状况调整数据传输速率。
-
高效传输:UDP适用于对速度要求较高,但对数据完整性要求不高的应用,如实时视频流、在线游戏、VoIP等。
总结来说,TCP和UDP各有优缺点,选择哪种协议取决于具体的应用需求。如果需要可靠的数据传输,TCP是更好的选择;如果对速度要求较高,对数据完整性要求不高,UDP则更为合适。
ModBUS,
ModBUS是一种串行通信协议,主要用于工业自动化领域,特别是用于连接现场设备(如传感器、执行器、PLC等)和监控系统。ModBUS协议是一种基于主从结构的通信协议,它定义了设备之间如何通过串行通信接口交换数据。
ModBUS协议的主要特点包括:
-
主从结构:ModBUS协议采用主从结构,其中有一个主设备(Master)和多个从设备(Slave)。主设备负责发起通信请求,而从设备则响应请求。
-
简单性:ModBUS协议设计简单,易于实现和理解。它使用标准的串行通信接口,如RS-232、RS-485等。
-
灵活性:ModBUS协议支持多种数据传输模式,包括ASCII和RTU(远程终端单元)模式。RTU模式通常用于数据传输速率较高的情况。
-
地址范围:ModBUS协议使用从机地址来标识不同的从设备,地址范围通常从0到247。
-
数据类型:ModBUS协议定义了多种数据类型,如16位无符号整数、32位无符号整数、16位浮点数等,以适应不同的数据交换需求。
-
错误检测:ModBUS协议提供错误检测功能,包括CRC(循环冗余检查)校验,以确保数据的完整性和可靠性。
-
功能码:ModBUS协议使用功能码来指示数据传输的目的,如读取数据、写入数据、执行控制命令等。
-
广泛应用:ModBUS协议因其简单性和开放性,在工业自动化领域得到了广泛的应用,成为了一种事实上的标准。
ModBUS协议的广泛应用使得它成为连接各种现场设备和监控系统的重要桥梁,它支持多种数据传输速率,从9600 bps到115200 bps不等,并且可以适应不同的网络拓扑结构。
数据结构
算法
常见算法
两个以上排序算法
选择排序:
public void xuanZhe(int[] list)//选择排序
{
for (int i = 0; i < list.Length – 1; i++)
{
min = i;
for (int j = i + 1; j < list.Length; j++)
{
if (list[j] < list[min])
min = j;
}
int t = list[min];
list[min] = list[i];
list[i] = t;
}
}
冒泡排序
#include <stdio.h>
void bubble_sort(int arr[], int len) {
int i, j, temp;
for (i = 0; i < len - 1; i++)
for (j = 0; j < len - 1 - i; j++)
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
int main() {
int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
int len = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, len);
int i;
for (i = 0; i < len; i++)
printf("%d ", arr[i]);
return 0;
}
算法题
力扣42接雨水
class Solution {
public int trap(int[] height) {
int left = 0;
int sum = 0;
for(int i=1;i<height.length;i++){
if(height[i]<height[left]){
continue;
}else{
if(i-left>1){ // 此时的柱子比left柱子高,且两柱子之间有间隙可接水
sum+=height[left]*(i-left-1);
for(int j=left+1;j<i;j++){
sum-=height[j]; // 减掉中间矮柱子占用空间
}
}
left = i; // 更换left柱子
}
}
// left下标即最高的柱子,可用来减少循环数量了
int right = height.length-1;
for(int i=right-1;i>=left;i--){
if(height[i]<height[right]){
continue;
}else{
if(right-i>1){ // 此时的柱子比right柱子高,且两柱子之间有间隙可接水
sum+=height[right]*(right-i-1);
for(int j=i+1;j<right;j++){
sum-=height[j]; // 减掉中间矮柱子占用空间
}
}
right = i; // 更换right柱子
}
}
return sum;
}
}
第二题是在一个树类里实现一个compare方法,入参为一棵树,返回值为布尔值,要求能使用这个方法比较当前树与另一棵树是否相等
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
} else if (p.val != q.val) {
return false;
} else {
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
第三题是1000瓶水找毒药,挺经典的题目,用二进制做
base^n>1000 n就是只数。
第四题题干:木板原材料长度6米,三种零件需求的木板长度各不相同,分别为xxX,然后写一个算法,面对不同的零件数量需求,计算如何切割木板,使木板浪费最少。看起来像是要用动态规划来